通过“where's my car”制作初识地图控件(二)

一, 关于ios中地图控件的使用

  如果要在ios设备中使用地图控件,首先我们需要在页面上添加一个地图视图来显示地图信息。可以在storyboard中通过添加MapView来实现,注意,地图空间要连接代理,也就是在storyboard中右键点击mapview,然后将delegate连线到所在控制器上。

接下来,在工程中我们需要导入使用地图控件所需要的框架:

CoreLocation.framework以及MapKit.framework。然后再头文件中那个导入包,并定义相应变量

#import <UIKit/UIKit.h>
#import <MapKit/MKAnnotation.h>
#import <MapKit/MapKit.h>
#import <CoreLocation/CoreLocation.h>//注意导入
@interfaceZjViewController : UIViewController
@end
@interfaceSpotAnnotation : NSObject <MKAnnotation>{//重新添加了一个专门记录当前位置点的注视点类
    CLLocationCoordinate2D coordinate;//一个用来记录二维位置的类对象
    NSString *title;
    NSString *subtitle;
}
@property(nonatomic,assign)CLLocationCoordinate2Dcoordinate;
@property(nonatomic,copy)NSString *title;
@property(nonatomic,copy)NSString *subtite;
@end


同时不要忘记要在.m文件中添加代理

<MKMapViewDelegate,CLLocationManagerDelegate,UIImagePickerControllerDelegate,UINavigationControllerDelegate>

注意,上面四个代理分别用于:地图空间使用,当前位置记录,图片来源选择,Navigation界面推送使用。

然后将视图中的mapview连线到代码中作为IBOutlet属性值。下面就要通过代码设置相应函数来实现功能。

首先,进入软件之后地图会自动加载并定位到当前位置。但是由于范围过大不够精准,我们需要通过一个按钮来触发地图视角拉近至一定范围,所以添加按钮函数:

- (IBAction)click_big:(UIBarButtonItem *)sender {
   MKCoordinateRegion region = [_mapView region];//定义一个区域类的对象,这个对象的值是当前地图上显示的值。其中包含经度属性值和纬度属性值
    region.center = [_mapViewuserLocation].location.coordinate;//以用户当前所在地为中心缩小区域
    region.span.latitudeDelta = 0.02;//设置纬度的缩小范围
    region.span.longitudeDelta = 0.02;//设置经度的缩小
    [_mapView setRegion:region animated:YES];
    if([[NSUserDefaults standardUserDefaults]floatForKey:@"WIMCLat"]!= 0.000){
        CLLocationCoordinate2D coord;
        coord.latitude = [[NSUserDefaultsstandardUserDefaults]floatForKey:@"WIMCLat"];
        coord.longitude = [[NSUserDefaultsstandardUserDefaults]floatForKey:@"WIMCLng"];
        [self dropPinAtCoord:coord];
    }
}

这样我们就可以将地图缩小到一定范围了,接下来我们需要记录下当前我们所在的位置。在ios地图中,记录位置会有一个小动画是从地图上方落下一个大头针样的小图标定位在当前位置,这个点称为锚点,也就是用来记录位置。一次接下来,我们来设置关于这个锚点的函数:

-(MKAnnotationView *)mapView:(MKMapView *)mapViewviewForAnnotation:(id<MKAnnotation>)annotation{
    //这个大头针属于一个关于标注地点注释的类(锚点)
    if(![annotationisKindOfClass:[SpotAnnotation class]]){
        return nil;
    }
    NSString *dqref = @"停车点";
    id ac = [mapViewdequeueReusableAnnotationViewWithIdentifier:dqref];//为这个锚点添加一个表示为:“停车点”
    if(ac == nil){
    //如果当前地图上不存在这样一个锚点(大头针),说明当前还没有记录某个位置
        ac = [[MKPinAnnotationViewalloc]initWithAnnotation:annotation reuseIdentifier:dqref];//添加一个新的锚点类对象,属于MKPinAnnotationView类
        [acsetPinColor:MKPinAnnotationColorGreen];//设置大头针的颜色。可以有红绿灰三种选择
        [ac setAnimatesDrop:YES];//设置落下的动画
        [ac setCanShowCallout:YES];//使这个锚点上方可以出现一个小弹框
    }
    return ac;
}<span style="font-family: Arial, Helvetica, sans-serif;"> </span>

这样我们就定义了这样一个锚点,但是我们还没有噶偶这个锚点应该降落在哪里,也就是他应该记录什么位置,下面我们来写一个函数让这个锚点记录我们当前所在位置而且这个位置可以存储在我们的手机软件的文件夹目录下。

-(void)dropPinAtCoord:(CLLocationCoordinate2D)coord{
    //添加一个可以记录位置的锚点,也就是定位了用户停车的位置
    if([_mapView annotations].count>1){
        //表示地图上已经有了大头针,而现在又想要添加
        [_mapView removeAnnotation:[[_mapViewannotations] objectAtIndex:1]];//先把之前的大头针移除掉
    }
    SpotAnnotation *ann =[[SpotAnnotationalloc]init];//定义一个新的锚点
    [ann setCoordinate:[_mapViewuserLocation].location.coordinate];//设置这个锚点的位置是当前所在位置
    [_mapView addAnnotation:ann];//将锚点添加至地图上
    //新加锚点的时候先去除之前的锚点再添加新的锚点
    [self doRevGeocodeUsingLat:coord.latitudeandLng:coord.longitude];//这个自定义的函数是用来通过反向地理编码来寻找所在位置的地址信息
    [[NSUserDefaultsstandardUserDefaults]setFloat:coord.latitude forKey:@"WIMCLat"];//将记录保存在相应key值下
    [[NSUserDefaultsstandardUserDefaults]setFloat:coord.longitude forKey:@"WIMCLng"];
    //上面三行代码用来讲听着地点的位置存储在用户配置中
   
}

这样,我们的锚点就会出现在当前我们所在位置了,具体的实现是通过反向编码获取到当时停车点位置的经纬度,然后记录下来,这里需要用到反向地理编码函数来实现:

-(void)doRevGeocodeUsingLat:(float)lat andLng:(float)lng{
    //通过反向地理编码来寻找所在位置的地址信息
    CLLocation *c= [[CLLocationalloc]initWithLatitude:lat longitude:lng];//先定义一个用来记录位置的类对象
    CLGeocoder *revGeo = [[CLGeocoder alloc]init];
    [revGeo reverseGeocodeLocation:ccompletionHandler:^(NSArray *placemarks, NSError *error) {
        if(!error &&[placemarkscount]>0){
            NSDictionary *dict = [[placemarksobjectAtIndex:0] addressDictionary];
            NSString *loc = [NSStringstringWithFormat:@"%@",[dict valueForKey:@"Name"]];
            NSLog(@"%@",loc);
            for(SpotAnnotation *ann in[_mapView annotations]){
                if([annisKindOfClass:[SpotAnnotation class]]){
                    [ann setTitle:loc];//将这个位置信息显示在锚点上方的注释信息框中
                }
            }
        }else{
            NSLog(@"错误");
        }
    }];
//reverseGeocodeLocation:completionHandler更新在标注进行循环,然后检索单个 的SpotAnnotation实例,一旦检索到了结果,反向地理编码就会返回街道地址。
}


这样我们就可以记录当下位置,并且在下次打开软件时显示出我没记录的位置。

接下来,我们还需要其他一些小功能,比如记录一些文字便签:

- (IBAction)click_addNote:(UIBarButtonItem *)sender {
    [_doneBtnsetHidden:NO];//将“完成”按钮显示出来(默认属性设置成了不显示)
    [_textView setHidden:NO];//将文本编辑框显示出来(默认属性设置成了不显示)
    [_textView becomeFirstResponder];//让当前文本框称为编辑第一响应者,用于键盘的编辑
    [_textView setText:[[NSUserDefaultsstandardUserDefaults] objectForKey:@"Note" ]]; //文本框中显示的内容是从文件夹目录下相对应的记录文件中提取出来的。
}
- (IBAction)click_doneAddNote:(UIButton *)sender {
    //编写完成后点击了“完成按钮”执行
    [_textView setHidden:YES];
    [_doneBtn setHidden:YES];//再次隐藏按钮以及编辑框
    [_textView resignFirstResponder];//取消文本编辑框的第一响应者身份使键盘隐藏
    [[NSUserDefaults standardUserDefaults]setObject:[_textView text] forKey:@"Note"];//将文本框中输入的文字保存在文件夹目录下相对应的记录文件中,方便下次显示
}
 


其后,我们还需要使用照相功能,找一张照片然后保存在文件夹目录下方便下次打开软件是取出显示:

+ (UIImage*)imageWithImage:(UIImage*)image
                 scaledToSize:(CGSize)newSize;
{
     UIGraphicsBeginImageContext(newSize );
     [imagedrawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
     UIImage*newImage = UIGraphicsGetImageFromCurrentImageContext();
     UIGraphicsEndImageContext();
     returnnewImage;
}
-(NSString*)imagePath
{//这里的函数用来定义一个用来保存照片的路径,这个文件在软件的文件夹中document文件夹下。照片名字为WIMCpic.png
     NSArray *paths= NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask,YES);
     NSString*documentsDirectoryPath = [paths objectAtIndex:0];
     NSString*imgPath = [NSString stringWithFormat:@"%@/WIMCApp/",
                              documentsDirectoryPath];
     NSError *err;
     [[NSFileManagerdefaultManager]
      createDirectoryAtPath:imgPathwithIntermediateDirectories:YES
      attributes:nil error:&err];
    
     return[NSString stringWithFormat:
            @"%@WIMCpic.png", imgPath];
}
- (IBAction)click_takePhone:(UIBarButtonItem *)sender {
   UIImagePickerController *ipController = [[UIImagePickerController alloc]init];
     if ([[[UIDevicecurrentDevice] model]
           rangeOfString:@"Sim"].location ==NSNotFound)
       [ipController setSourceType:UIImagePickerControllerSourceTypeCamera];
     [ipControllersetDelegate:self];/!!!!!!!!!!!!!!!!!!!!!!!
     [selfpresentViewController:ipController animated:YES completion:^{
       
    }];
}
- (void)imagePickerController:(UIImagePickerController*)picker
didFinishPickingMediaWithInfo:(NSDictionary *)info
{
     UIImage *pic = [infoobjectForKey:UIImagePickerControllerOriginalImage];
     pic =[ZjViewController imageWithImage:pic
                                     scaledToSize:CGSizeMake(320.0, 460.0)];
     [UIImagePNGRepresentation(pic)
    writeToFile:[self imagePath] atomically:YES];
     [selfdismissModalViewControllerAnimated:YES];
}
- (IBAction)click_phone:(UIBarButtonItem *)sender {
    UIImage *image= [UIImage imageWithContentsOfFile:[self imagePath]];
    if(image ==nil){
        return;
    }
    UIStoryboard *s= [UIStoryboard storyboardWithName:@"Main" bundle:nil];
    picController*p = [s instantiateViewControllerWithIdentifier:@"picController"];
    p.PicImage = image;
    [selfpresentViewController:p animated:YES completion:^{
    }];
}

上面的代码主要是使用照相机设备然后进行照片选择,具体讲解参考之前一篇文章关于ios相机设备的使用

 至此就完成了大多数功能,但是还需要将头文件中新加的类做一个实现说明:

@implementation SpotAnnotation
@synthesize title, subtitle, coordinate;
@end

我们还应该添加一个控制器类专门用来显示我们照相获取的相片,这里不再说明,只需要新建一个控制器类,添加一个imageView并将照片传递显示在其上即可。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值