地图与标记

显示地图

在地图的头文件中#import <MapKit/MapKit.h>

在地图的头文件中还要引入协议<MKMapViewDelegate>

代码如下:

1
2
3
4
5
6
7
8
9
#import <UIKit/UIKit.h>
#import <MapKit/MapKit.h>
#import "MapLocation.h"
@interface AnnotationViewController : UIViewController <MKMapViewDelegate>
@property (nonatomic) CLLocationDegrees longitude; // 经度
@property (nonatomic) CLLocationDegrees latitude; // 纬度
@property (strong, nonatomic) NSString *institutionName; // 名称
@property (strong, nonatomic) NSString *locationName; // 地址名称
@end

在地图的controller中声明MKMapView

代码如下:

1
2
3
4
5
6
@interface AnnotationViewController ()
@property (strong, nonatomic) MKMapView *mapView; // 地图view
@property (nonatomic) CLLocationDistance latitudinalMeters; // 纬度放大倍数
@property (nonatomic) CLLocationDistance longitudinalMeters; // 经度放大倍数
@property (nonatomic, strong) CLGeocoder *geocoder; // 反编码
@end

初始化地图view和协议

代码如下:

1
2
3
4
5
6
7
- (void)initMap
{
_mapView = [[MKMapView alloc]initWithFrame:CGRectMake(0, 64, DF_WIDTH, DF_HEIGHT-64)];
[self.view addSubview:_mapView];
_mapView.mapType = MKMapTypeStandard;
_mapView.delegate = self;
}

自定义地图地址模型

location模型头文件代码如下,感觉其实除了遵守<MKAnnotation>协议以外其他的暂时没什么用,只用到了<MKAnnotation>里面的titlesubtitle

1
2
3
4
5
6
7
8
9
10
11
#import <Foundation/Foundation.h>
#import <MapKit/MapKit.h>
@interface MapLocation : NSObject<MKAnnotation>
@property (nonatomic, readwrite) CLLocationCoordinate2D coordinate; //
@property (nonatomic, copy) NSString *streetAddress; // 街道信息属性
@property (nonatomic, copy) NSString *city; // 城市信息属性
@property (nonatomic, copy) NSString *state; // 邮编
@property (nonatomic, copy) NSString *zip; // 地理坐标
@property (nonatomic, copy) NSString *title; // 标题
@property (nonatomic, copy) NSString *subtitle; // 副标题
@end

location的m文件代码如下:用了懒加载。因为在’mapViewController’中会赋值给这两个property,所以感觉也并没有什么用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
@implementation MapLocation
- (NSString *)title {
if(!_title) _title = @"XXX";
return _title;
}
- (NSString *)subtitle {
if(!_subtitle){
NSMutableString *ret = [NSMutableString new];
if(_state)
[ret appendString:_state];
if(_city)
[ret appendString:_city];
if(_city && _state)
[ret appendString:@","];
if(_streetAddress && (_city || _state || _zip))
[ret appendString:@"·"];
if(_streetAddress)
[ret appendString:_streetAddress];
if(_zip)
[ret appendFormat:@", %@", _zip];
_subtitle = ret;
}
return _subtitle;
}
@end

annocation大头针定位

关于大头针的view

1
2
3
4
5
6
7
8
9
10
11
- (MKAnnotationView *)mapView:(MKMapView *)mapView viewForAnnotation:(id<MKAnnotation>)annotation
{
MKPinAnnotationView *annotationView = (MKPinAnnotationView *)[_mapView dequeueReusableAnnotationViewWithIdentifier:@"PIN_ANNOTATION"];
if(!annotationView){
annotationView = [[MKPinAnnotationView alloc]initWithAnnotation:annotation reuseIdentifier:@"PIN_ANNOTATION"];
}
annotationView.pinColor = MKPinAnnotationColorRed;
annotationView.animatesDrop = YES;
annotationView.canShowCallout = YES;
return annotationView;
}

关于有经纬度编码+反编码的部分

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
CLLocation *location = [[CLLocation alloc] initWithLatitude:self.latitude longitude:self.longitude];
self.geocoder = [[CLGeocoder alloc] init];
[self.geocoder reverseGeocodeLocation:location
completionHandler:^(NSArray *placemarks, NSError *error)
{
if (error == nil && [placemarks count] > 0){
[_mapView removeAnnotations:_mapView.annotations];
for(int i=0;i<[placemarks count];i++)
{
CLPlacemark *placemark = placemarks[i];
// 调整地图位置和缩放比例
MKCoordinateRegion viewRegion = MKCoordinateRegionMakeWithDistance(placemark.location.coordinate, self.latitudinalMeters, self.longitudinalMeters);
[_mapView setRegion:viewRegion animated:YES];
MapLocation *annotation = [[MapLocation alloc]init];
annotation.title = self.XXXName;
annotation.subtitle = self.locationName;
annotation.streetAddress = placemark.thoroughfare;
annotation.city = placemark.locality;
annotation.state = placemark.administrativeArea;
annotation.zip = placemark.postalCode;
annotation.coordinate = placemark.location.coordinate;
[_mapView addAnnotation:annotation];
}
}
else if (error == nil && [placemarks count] == 0){
NSLog(@"No results were returned.");
}
else if (error != nil){
NSLog(@"An error occurred = %@", error);
}
}];

iOS开发随笔-3

协议与委托

这次做项目,用到了一点点协议与委托的东西,把我学到的东西总结一下:

委托和协议是两个概念,协议实际上相当于C++中的纯虚类的概念,只定义并只能由其它类来实现。而委托类似于Java中的接口。

协议@protocol就是多个文件共同遵守,里面的方法默认必须实现@required,也可以设置可选@optional

委托delegate就是A要实现一个方法,但是A没有,就委托B去实现。委托不一定非要用协议来实现。

在这次的项目中,用到了一点协议与委托。

  • 在view.h中声明协议
1
2
3
4
@protocol XXXDelegate <NSObject>
@optional
- (void)XXX;
@end
  • 在view.h的interface中也要声明:

@property (nonatomic, assign) id <XXXDelegate> delegate; // 协议声明'

  • 在view.h中像调用对象一样调用delegate:

[self.delegate XXX];

  • 在实现委托的文件中,比如viewController中,引入delegate:

@interface XXXTableViewController ()<XXXDelegate>

  • 在需要实现协议的控件上:

headView.delegate = self;

  • 最后要实现协议中的方法。

iOS开发笔记-7

拨打电话的三种方法

  1. 这种方法,拨打完电话回不到原来的应用,会停留在通讯录里,而且是直接拨打,不弹出提示
1
2
NSMutableString * str=[[NSMutableString alloc] initWithFormat:@"tel:%@",@"186xxxx6979"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:str]];
  1. 这种方法,打完电话后还会回到原来的程序,也会弹出提示,推荐这种
1
2
3
4
5
6
NSMutableString * str=[[NSMutableString alloc] initWithFormat:@"tel:%@",@"186xxxx6979"];
UIWebView * callWebview = [[UIWebView alloc] init];
[callWebview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:str]]];
[self.view addSubview:callWebview];
[callWebview release];
[str release];
  1. 这种方法也会回去到原来的程序里(注意这里的telprompt),也会弹出提示
1
2
NSMutableString * str=[[NSMutableString alloc] initWithFormat:@"telprompt://%@",@"186xxxx6979"];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:str]];

底部弹出视图

项目中的底部弹出视图使用的ZZActionSheet

具体使用方法:

  • 引入头文件和协议

import "ZZActionSheet.h"

@interface ViewController ()< ZZActionSheetDelegate>

  • 点击按钮触发底部弹出框:
1
2
3
4
5
6
7
8
9
//底部弹出框
ZZActionSheet *actionSheet =
[[ZZActionSheet alloc] initWithTitle:nil
delegate:self
cancelButtonTitle:@"取消"
destructiveButtonTitle:nil
otherButtonTitles:self.telArray];
actionSheet.tag = 0;
[actionSheet showInView:self.view];
  • 实现协议
1
2
3
4
#pragma mark - ZZActionSheetDelegate
- (void)ZZActionSheet:(ZZActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
//buttonIndex就是从上到下按钮的index
}

ios开发随笔-2

布局问题

最近经常遇到莫名其妙的布局问题,感觉明明代码写对了,却不是自己想要的样子。

检查发现,其实还是自己粗心大意:

  • 写布局的时候经常复制粘贴,然后粘贴上来的代码有的控件名字忘记改。
  • 写cell文件的时候,其实它自带有imageView、lineView之类的控件(注意这些控件名是蓝色的!),然而我自己的控件总是起一个类似于这个的名字如imageview、lineview(这些控件名是绿色的!),在写代码的时候就很容易混淆。以后尽量不要起这样容易混淆的名字!

ios开发笔记-6

设置TableView Separatorinset 分割线从边框顶端开始

在ios8上[TableView setSeparatorInset:UIEdgeInsetsMake(0,0,0,0)];不起作用

可使用如下方法:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
-(void)viewDidLayoutSubviews
{
if ([self.tableView respondsToSelector:@selector(setSeparatorInset:)]) {
[self.tableView setSeparatorInset:UIEdgeInsetsMake(0,0,0,0)];}
if ([self.tableView respondsToSelector:@selector(setLayoutMargins:)]) {
[self.tableView setLayoutMargins:UIEdgeInsetsMake(0,0,0,0)];}
}
-(void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([cell respondsToSelector:@selector(setSeparatorInset:)]) {
[cell setSeparatorInset:UIEdgeInsetsZero];}
if ([cell respondsToSelector:@selector(setLayoutMargins:)]) {
[cell setLayoutMargins:UIEdgeInsetsZero];}
}

调整UITableViewCell的宽度

UITableViewCell的宽度会在添加到TableView的时候被重设,所以在- (UITableViewCell *)talbeView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath里面设置cell的宽度是没用的。
新建一个UITableViewCell的子类,然后重写它的-setFrame:方法即可。

1
2
3
4
5
- (void)setFrame:(CGRect)frame {
frame.origin.x += kCellLeft;
frame.size.width -= 2 * kCellLeft;
[super setFrame:frame];
}

UILabel显示边框

  • 添加框架 QuartzCore.framework
  • 引入头文件#import "QuartzCore/QuartzCore.h"
  • 添加代码:
1
2
self.label.layer.borderColor = [UIColor redColor].CGColor;
self.label.layer.borderWidth = 2.0;

UILabel设置圆角

view.layer.cornerRadius = 5;

详情请见技术博客http://www.jianshu.com/p/f970872fdc22

ios开发笔记(5)

“Auto property synthesis will not synthesize property ‘imageView’…”问题的解决

Auto property synthesis will not synthesize property ‘imageView’ because it is ‘readwrite’ but it will be synthesized ‘readonly’ via another property. 我在自定义UITableViewCell的.h文件里面添加属性
@property(nonatomic,strong)UIImageView *imageView;

解决方法:

把@property(nonatomic,strong)UIImageView *imageView;
这里的imageView名字改一下就行了,imageView好像跟系统自带属性有冲突.

ios开发笔记(4)

“this class is not key value coding-compliant for the key …”问题的解决

一般此问题 都是由interface build与代码中IBOutlet的连接所引起的。

可能是在代码中对iboutlet的名称进行了修改,导致interface build中的连接实效。

这次我的代码中出现这个问题的原因就是对iboutlet的名称进行了修改,之后删掉代码之后重新连,仍然不行。

这时是因为只是删除了代码,而之前的连接线还没有删除,所有右键单击的话会发现有两个连接线。