0 编程习惯
在viewDiUnload中重置变量为nil
- (void)viewDidUnload { [super viewDidUnload]; self.mapView = nil; self.infoButton = nil; self.tocViewController = nil; if([[AGSDevice currentDevice] isIPad]) self.popOverController = nil; }
1 为按钮控件增加事件处理
方法1:从storyboard中拖动按钮到controller.h中,选择Action,然后输入操作方法名即可,在controller.h controller.m中都有自动生成的代码
或者事先在.h文件中写好Action操作函数,然后在xib文件中拖动控件到File's owner上,注意File's owner的类
方法2:选择Outlet,然后输入Name,然后在controller.m中手动添加处理方法
//为按钮绑定事件 [_btnLayers addTarget:self action:@selector(changeLayerAction:) forControlEvents:UIControlEventTouchUpInside];
-(void) changeLayerAction:(id)sender { // UIAlertView *alertView=[[UIAlertView alloc] initWithTitle:@"温馨提示" // message:@"我被单击了!" // delegate:nil // cancelButtonTitle:@"OK" // otherButtonTitles:nil]; // [alertView show]; }
2 增加委托
方法1 控件的storyboard界面方式。按住control键退动文本框到界面黄色标记的按钮上,点击delegate选项,然后在controller.h controller.m中分别添加代码
@interface dcecViewController : UIViewController<UITextFieldDelegate>
- (BOOL)textFieldShouldReturn:(UITextField *)textField { if (textField==self.textField1 || textField==self.textField2) { [textField resignFirstResponder]; } return YES; }
方法2,在代码中设置
在controller.h中
@interface dcecViewController : UIViewController<UISearchBarDelegate>
//搜索框 _searchBar=[[UISearchBar alloc]initWithFrame:CGRectMake(0,0,320,41)]; _searchBar.delegate=self; _searchBar.placeholder=@"名字 "; _searchBar.showsSearchResultsButton=YES; [_mapView addSubview:_searchBar];
//SearchBar协议的方法实现 - (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar { }
3 引入第三方库
http://mobile.51cto.com/iphone-407056.htm
方法一:直接复制所有源文件到项目中
这种方法就是把第三方类库的所有源文件复制到项目中,直接把所有.h和.m文件拖到XCode项目中即可。如果第三方类库引用了一些系统自带类库,那么在项目中还需要额外引用那些类库。
如果当前的项目启用了ARC,而引用的第三方类库未使用ARC,那还需要在项目信息的Targets – Build Parses里找到第三方类库的.m文件,并为它们加上-fno-objc-arc标记。
而对于在未启用ARC的项目用引用使用了ARC的第三方类库,则需要为第三方类库的.m文件加上-fobjc-arc标记。
另外,在源代码中可以通过一个编译器指令__has_feature(objc_arc)来检测项目是否使用了ARC,具体见http://clang.llvm.org/docs/LanguageExtensions.html#langext-has-feature-has-extension。
方法二:引用.xcodeproj生成静态链接库并引用
首先,在XCode中把第三方类库的.xcodeproj文件拖到当前项目中;如果第三方类库封装了一些资源在.bundle文件里,那么.bundle文件需要和.xcodeproj一起拖到项目中。
然后,在项目的Targets – Summary – Linked Frameworks and Libraries或者在Targets – Build Phases – Link Binary With Libraries添加第三方类库生成的静态链接库引用。
接着,还需要在Targets – Build Settings – Search Paths的User Header Search Paths参数中加入第三方类库的头文件路径,可以是绝对路径如:/Users/libpath,也可以是相对路径(相对于当前项目文件夹)如:../**。
最后,有些静态链接库引用进来可能还需要增加一些标记,在Targets – Build Settings – Linking的Other Linker Flags参数中增加:-Objc, –all_load这一类标记。
通过以上几步,一般都可以成功编译。
当然还有一些例外的情况:
- 当前项目和第三方类库同时使用了另外的一些第三方类库,这个时候还需要额外做一些处理才能成功编译:在引用的第三方类库的.xcodeproj项目 – Targets – Build Phases中的Compile Sources和Copy Headers把重复的.m和.h文件移除掉。
- 第三方类库引用的一些系统自带类库,如果项目中没有引用,也可能会引起编译错误,这时还需要在项目中引用第三方类库引用的一些系统自带类库。比如:第三方类库引用了QuartzCore.framework,而项目中未引用QuartzCore.framework则可能引起编译错误,就需要在项目中也引用QuartzCore.framework。
4 UITableviewCell添加自定义控件
//ManagerLayers.h文件 #import <UIKit/UIKit.h> #import "MyCell.h" #define NotificationLayerChange @"NotificationLayerChange" @interface ManagerLayers : UITableViewController { NSArray *layers; } @property (strong, nonatomic) IBOutlet MyCell *tvc; @property (strong,nonatomic) UIPopoverController *container; @property NSInteger selIndex; @end //ManagerLayers.m文件 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //方法1,在代码中增加一个子视图 static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; //标签 UILabel *label=[[UILabel alloc]init]; label.frame=CGRectMake(1,0,60, cell.contentView.bounds.size.height); label.tag=1; [cell.contentView addSubview:label]; //slider UISlider *slider=[[UISlider alloc]initWithFrame:CGRectMake(65,10,150,cell.contentView.bounds.size.height)]; slider.minimumValue = 0;//指定可变最小值 slider.maximumValue = 100;//可变最大值 slider.value = 50;//指定初始值 slider.tag=2; [slider addTarget:self action:@selector(sliderAction:event:) forControlEvents:UIControlEventValueChanged];//设置响应事件 [cell.contentView addSubview:slider]; //开关类型 UISwitch *switchview = [[UISwitch alloc] initWithFrame:CGRectZero]; switchview.tag=3;//[indexPath row];//在后面可以直接使用这个tag来确定是触发了哪个cell [switchview addTarget:self action:@selector(switchAction:) forControlEvents:UIControlEventValueChanged]; cell.accessoryView = switchview; //cell.accessoryType=UITableViewCellAccessoryCheckmark; //cell.accessoryType=UITableViewCellAccessoryNone; } UILabel *label=(UILabel*)[cell viewWithTag:1]; label.text=[layers objectAtIndex:indexPath.row]; // //方法2, 定义cell类 // static NSString *CellIdentifier = @"LayerCell"; // // LayerCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; // if (cell == nil) { // NSArray *array = [[NSBundle mainBundle]loadNibNamed:CellIdentifier owner:self options:nil]; // cell = [array objectAtIndex:0]; // } // cell.label.text = [layers objectAtIndex:indexPath.row]; // //方法3,定义cell类,并设置file's owner和添加输出口变量与对应 //将MyCell.xib文件的file‘s owner关联到ManagerLayer类,然后在ManagerLayer.h中添加输出口tvc并赋予MyCell.xib的file's owner. //static NSString *cellIdentifier=@"MyCell"; //MyCell *cell=[tableView dequeueReusableCellWithIdentifier:cellIdentifier]; //if(cell==nil) //{ // [[NSBundle mainBundle] loadNibNamed:@"MyCell" owner:self options:nil]; // cell=self.tvc; //} //引用控件方式1 //通过设置xib的uitableviewcell的继承类,并添加在MyCell.h中添加了输出口属性的方式访问label控件 //cell.label.text=[layers objectAtIndex:indexPath.row]; //引用控件方式2 //在xib中设置了label的tag属性,然后在此通过这个属性调用label //UILabel *label=(UILabel*)[cell viewWithTag:2]; //label.text=[layers objectAtIndex:indexPath.row]; return cell; }
//响应方法。通过点击位置确定操作的cell
- (void) sliderAction:(id)sender event:(id)event { NSSet *touches = [event allTouches]; UITouch *touch = [touches anyObject]; CGPoint currentTouchPosition = [touch locationInView:self.tableView]; NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:currentTouchPosition]; if(indexPath != nil) { //[self tableView:self.tableView accessoryButtonTappedForRowWithIndexPath:indexPath]; _selIndex=indexPath.row; [[NSNotificationCenter defaultCenter] postNotificationName:NotificationLayerChange object:self]; } } //响应方式,通过获取父视图确定操作的cell - (void)switchAction:(id)sender { UISwitch *switchLayer=(UISwitch*)sender; UITableViewCell *cell=(UITableViewCell*)[[sender superview]spuerview]; NSIndexPath *indexPath=[self.tableView indexPathForCell:cell]; NSInteger selectIndex=[indexPath row]; NSLog(@"---%d----",selectIndex); }
示例二
#pragma mark - #pragma mark Tabel Datasource Methods - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return 20; } - (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //方式一,自定义一个tableViewCell子类,关联一个xib文件 // static NSString *customCellIdentifier=@"CustomCell"; // static BOOL nibsRegistered = NO; // if (!nibsRegistered) { //注意这种赋值方式 // UINib *nib = [UINib nibWithNibName:@"CustomCell" bundle:nil]; // [tableView registerNib:nib forCellReuseIdentifier:customCellIdentifier]; // nibsRegistered = YES; // } // // CustomCell *customCell=[tableView dequeueReusableCellWithIdentifier:customCellIdentifier]; // NSString *num=[NSString stringWithFormat:@"%d",indexPath.row]; // customCell.label.text=num; // return customCell; //方式二,单独采用xib文件 UITableViewCell *cell=[tableView dequeueReusableCellWithIdentifier:@"CustomCellIdentifier2"]; if (!cell) { //注意这种赋值方式 cell=[[[NSBundle mainBundle]loadNibNamed:@"CustomCell2" owner:self options:nil]lastObject]; } NSString *num=[NSString stringWithFormat:@"%d",indexPath.row]; UILabel *label=(UILabel*)[cell viewWithTag:12]; label.text=num; return cell; } #pragma mark Table Delegate Methods - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return 60.0; } - (NSIndexPath*)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath { return nil; } @end
自定义cell的消息传递方法1、通知的方式
2、委托的方式
在cell中定义委托,如下
xxxCell.h文件
#import <Foundation/Foundation.h> //声明协议 @protocol LayerInfoCellDelegate; @interface LayerInfoCell : UITableViewCell { UILabel *_valueLabel; id <LayerInfoCellDelegate> __weak _layerInfoCellDelegate; } @property (nonatomic, strong) UILabel *valueLabel; @property (nonatomic, weak) id <LayerInfoCellDelegate> layerInfoCellDelegate; - (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier level:(NSUInteger)level canChangeVisibility:(BOOL)canChangeVisibility visibility:(BOOL)visibility expanded:(BOOL)expanded; @end //协议 @protocol LayerInfoCellDelegate <NSObject> - (void)layerVisibilityChanged:(BOOL)visibility forCell:(UITableViewCell *)cell; @end
在xxxCell.m文件中使用delegate
- (IBAction)visibilityChanged { [self.visibilitySwitch changeCheckBox]; [self.layerInfoCellDelegate layerVisibilityChanged:self.visibilitySwitch.isChecked forCell:self]; } //在deallloc中重置为nil - (void)dealloc { self.layerInfoCellDelegate = nil; }
在调用xxxCell的类中实现delegate协议、实现委托方法
@interface TOCViewController() <LayerInfoCellDelegate, UITableViewDelegate, UITableViewDataSource>
//使用委托的方式,在cell中操作委托给调用cell的类 - (void)layerVisibilityChanged:(BOOL)visibility forCell:(UITableViewCell *)cell { //retrieve the corresponding cell NSIndexPath *cellIndexPath = [self.tableView indexPathForCell:cell]; //get the layer info represented by the cell LayerInfo *layerInfo = [[self.mapViewLevelLayerInfo flattenElementsWithCacheRefresh:NO withLegend:YES] objectAtIndex:(cellIndexPath.row)]; //set the visibility of the layer info. [layerInfo setVisible:visibility]; }
5. 访问WebService服务
(1)SOAP
采用第三方库ASIHTTPRequest
- (BOOL)textFieldShouldReturn:(UITextField *)textField { NSLog(@"Want to redeem: %@", textField.text); // Get device unique ID UIDevice *device = [UIDevice currentDevice]; NSString *uniqueIdentifier = [device uniqueIdentifier]; // Start request NSString *code = textField.text; // NSURL *url = [NSURL URLWithString:@"http://192.168.133.179:7777/CXFDemo/ws/v1/say/1"]; NSURL *url=[NSURL URLWithString:@"http://192.168.133.179:7777/CXFDemo/ws/helloService"]; ASIHTTPRequest *request=[ASIHTTPRequest requestWithURL:url]; // ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; // [request setPostValue:@"1" forKey:@"rw_app_id"]; // [request setPostValue:code forKey:@"code"]; // [request setPostValue:uniqueIdentifier forKey:@"device_id"]; // NSString *soapMsgBody=@"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:q0=\"http://server.dcec/\" xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\">\n<soapenv:Body>\n<q0:test>\n<arg0>fafadfadf</arg0>\n</q0:test>\n</soapenv:Body>\n</soapenv:Envelope>"; NSString *soapMsgBody = [NSString stringWithFormat: @"<?xml version=\"1.0\" encoding=\"utf-8\"?>" "<soapenv:Envelope " "xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" " "xmlns:q0=\"http://server.dcec\">" "xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " "xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " "<soapenv:Body>" "<q0:test>" "<arg0>苏州</arg0>" "</q0:test>" "</soapenv:Body>" "</soapenv:Envelope>"]; NSLog(@"%@",soapMsgBody); NSString *msgLength=[NSString stringWithFormat:@"%d",[soapMsgBody length]]; [request addRequestHeader:@"Content-Type" value:@"txt/xml; charset=utf-8"]; //[request addRequestHeader:@"SOAPAction" value:@"http://server.dcec/helloService\""]; //value:[NSString stringWithFormat:@"%@%@", xmlNS, wsName]]; [request addRequestHeader:@"Content-Length" value:msgLength]; [request setRequestMethod:@"POST"]; [request appendPostData:[soapMsgBody dataUsingEncoding:NSUTF8StringEncoding]]; [request setDefaultResponseEncoding:NSUTF8StringEncoding]; [request setDelegate:self]; [request startAsynchronous]; // Hide keyword [textField resignFirstResponder]; // Clear text field textView.text = @""; // Start hud MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES]; hud.labelText = @"Redeeming code..."; return TRUE; } - (void)requestFinished:(ASIHTTPRequest *)request { [MBProgressHUD hideHUDForView:self.view animated:YES]; if (request.responseStatusCode == 400) { textView.text = @"Invalid code"; } else if (request.responseStatusCode == 403) { textView.text = @"Code already used"; } else if (request.responseStatusCode == 200) { NSString *responseString = [request responseString]; NSDictionary *responseDict = [responseString JSONValue]; NSString *unlockCode = [responseDict objectForKey:@"unlock_code"]; // if ([unlockCode compare:@"com.razeware.test.unlock.cake"] == NSOrderedSame) { // textView.text = @"The cake is a lie!"; // } else { // textView.text = [NSString stringWithFormat:@"Received unexpected unlock code: %@", unlockCode]; // } NSLog(@"%@",responseString); textView.text=responseString; } else { textView.text = @"Unexpected error"; } } - (void)requestFailed:(ASIHTTPRequest *)request { [MBProgressHUD hideHUDForView:self.view animated:YES]; NSError *error = [request error]; textView.text = error.localizedDescription; }
(2)REST AFNetWorking 2.0框架处理
- (IBAction)action_test:(id)sender { // // UIAlertView *alert=[[UIAlertView alloc]initWithTitle:@"提示" // message:@"测试结果" // delegate:nil // cancelButtonTitle:@"取消" // otherButtonTitles:nil]; // [alert show]; //请求的URL需要添加_type=json //GET 请求一 // NSString *url =@"http://192.168.133.179:7777/ychserver/ws/v1/hello/say/33您好?_type=json"; // NSString *url2=@"http://192.168.133.179:7777/ychserver/ws/v1/hello/getUser/23/33?_type=json"; // AFHTTPRequestOperationManager *manager=[AFHTTPRequestOperationManager manager]; // [manager GET:url parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { // NSLog(@"JSON :\n%@",responseObject); // } failure:^(AFHTTPRequestOperation *operation, NSError *error) { // NSLog(@"错误 Error:%@",error); // }]; //GET 请求二 //http://192.168.133.179:7777/ychserver/ws/v1/hello/login?name=chen陈&pw=密码123&_type=json NSString *url =@"http://192.168.133.179:7777/ychserver/ws/v1/hello/login"; NSMutableDictionary *params=[NSMutableDictionary dictionary]; [params setObject:@"陈" forKey:@"name"]; [params setObject:@"密码123" forKey:@"pw"]; [params setObject:@"json" forKey:@"_type"]; AFHTTPRequestOperationManager *manager=[AFHTTPRequestOperationManager manager]; [manager GET:url parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"响应结果 \n%@",responseObject); //此时得到的是unicode方式的编码,测试的时候即后台服务设置输出utf-8的编码也会在此处变成unicode //,汉字不能正常输出。当把这个转成NSDictionary时,编码又自动转了,可以正常输出汉字 NSDictionary *info=(NSDictionary *)responseObject; NSLog(@"name %@",[info objectForKey:@"name"]); NSLog(@"pw %@",[info objectForKey:@"pw"]); //Dictionary转json if ([NSJSONSerialization isValidJSONObject:info]) { NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:info options:NSJSONWritingPrettyPrinted error:&error]; NSString *json =[[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; NSLog(@"json data:\n%@",json); } } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"错误 Error:%@",error); }]; NSLog(@"结束。。。"); }
6. ARC中__weak的使用
//当两个对象存在一种类似父子关系的时候,会用到它:parent拥有一个child的强指针,但是反过来,child却只有parent的一个弱指针。一个很典型的例子就是delegate。view controller 通过一个强指针保存一个UITableView对象,那么这个table view的delegate和data source就会用一个若指针指向这个viewcontroller,
可在property中声明一个对象的这个属性,如下:
@property (nonatomic, strong) NSString * aname; @property (nonatomic, weak) id<MyDelegate> delegate;
@interface LayerInfoCell : UITableViewCell { id <LayerInfoCellDelegate> __weak _layerInfoCellDelegate;//委托 }
说明:在A类中有B的实例,B的delegate是A,当A销毁时,若是strong强指针,则B中的A(delegate)依然存在,这样会引起错误;若使weak弱指针,则B中的delegate(A)就变成了nil.
7. 导航视图控制器的几种方式
在Delegate.h文件中声明一个导航控制器对象
@interface szdcecAppDelegate : UIResponder <UIApplicationDelegate>{ UINavigationController *navController; }
在Delegate.m文件中实例化
//自定义导航控制器 CityViewController *cityController=[[CityViewController alloc]init]; cityController.title=@"旅游指南"; //方式一,初始化根视图的方式 // navController =[[UINavigationController alloc]initWithRootViewController:cityController]; // self.window.rootViewController=navController; //方式二,调用push方法 // navController=[[UINavigationController alloc]init]; // [navController pushViewController:cityController animated:NO]; // [self.window addSubview:navController.view]; //方式三,调用setViewController方式 navController=[[UINavigationController alloc]init]; [navController setViewControllers:[NSArray arrayWithObject:cityController]]; //self.window.rootViewController=navController; [self.window addSubview:navController.view]; [self.window makeKeyAndVisible]; return YES;
两个视图传递参数
当A中定义了B的变量对象,可在A中调用B的属性变量,实现传递数据。在B中使用委托的方式,将B的数据传递给A。在B中定义委托,在A中实现委托赋值并实现委托的方法。
8. IOS字符集编码转换
(1)Unicode转汉字
//测试用例 name = "\U9648"; 陈 //pw = "\U5bc6\U7801123"; 密码123 - (NSString *)replaceUnicode:(NSString *)unicodeStr { NSString *tempStr1 = [unicodeStr stringByReplacingOccurrencesOfString:@"\\u"withString:@"\\U"]; NSString *tempStr2 = [tempStr1 stringByReplacingOccurrencesOfString:@"\""withString:@"\\\""]; NSString *tempStr3 = [[@"\""stringByAppendingString:tempStr2]stringByAppendingString:@"\""]; NSData *tempData = [tempStr3 dataUsingEncoding:NSUTF8StringEncoding]; NSString* returnStr = [NSPropertyListSerialization propertyListFromData:tempData mutabilityOption:NSPropertyListImmutable format:NULL errorDescription:NULL]; return [returnStr stringByReplacingOccurrencesOfString:@"\\r\\n"withString:@"\n"]; }