ios cell分割线相应事件可以和什么控件一起相应

小站会根据您的关注,为您发现更多,
看到喜欢的小站就马上关注吧!
下一站,你会遇见谁的梦想?
智捷iOS课堂-最专业iOS技术研究、应用研发、技术培训机构&iOS传播者&&&&
《iOS网络编程与云端应用最佳实践》微博转发送书了!
《iOS网络编程与云端应用最佳实践》微博转发送书了!
新浪微博地址:,转发本条微博即有机会获得《iOS网络编程与云端应用最佳实践》图书一本。
&& 现拿到出版社样书,应广大粉丝建议,搞一个微博转发送书,随机抽取转发粉丝送书3本。截止5月30日晚6点。在30日晚8点,会在多贝公开课《苹果电子商务探讨-iOS6 Passbook解析与开发》现场抽取中奖粉丝,公开课免费的,欢迎大家观看。多贝《苹果电子商务探讨-iOS6 Passbook解析与开发》公开课地址:
iOS网络编程-配置iCloud-图文解说
配置iCloud开发iCloud应用一方面需要准备真实的iOS设备,另一方面还需要有iOS开发者账号,使 用iOS开发者账号登录到iOS开发中心的配置门户网站(iOS&Provisioning&Portal&网址为 /ios/manage/overview/index.action),可以为应用做一些与 iCloud有关的配置工作。这些工作包括:&
创建App&ID首先需要为应用创建App&ID,App&ID是针对应用的注册,该过程是在配置门户网站完成的,开发者登录成功之后
点击左边导航菜单的App&IDs
点击&New&App&ID&按钮&
信息输入后点击&Submit&按钮提交信息,跳转到创建App&ID页面,在下面的App&ID列表中会发现我们刚刚创建的MyNotes
默认情况下创建的应用是不可以使用iCloud服务的,我们需要点击Configure超链接进入应用配置页面
配置完成点击右下角的&Done&按钮,保存配置并回到App&ID的列表页面,这时候再回来看一下我们刚刚配置的应用,它的iCloud状态变为了绿色可用状态了。
创建配置概要文件配 置概要文件(Provisioning&Profiles)是应用在设备上编译时使用的,文件分为开发配置概要和发布配置概要文件,分别用于开发(调试) 和发布。管理配置概要文件的页面通过左边的导航菜单Provisioning进入。其中Development标签用于管理开发配置概要文 件,Distribution标签用于管理发布配置概要文件,处理标签不同但它们的管理过程是完全一样的,本节介绍创建开发配置概要文件的过程。
点 击&New&Profile&按钮进入创建配置概要文件页面,在Profile&Name中输入 &MyNotes&Profile&,Certificates(证书),这是我们证书名,App&ID选择MyNotes。Devices项目是我们这 个配置概要文件所支持的设备,下面是注册的设备,勾选要用于调试的设备。
点击&Submit&按钮提交,页面跳转回管理配置概要文件页面。稍等一会儿刷新一下页面,配置概要文件创建完毕,点击MyNote&Profile行后面的Download按钮可以下载配置概要文件,点击Edit超链接进行页面修改。
为了能够实现设备调试我们需要下载配置概要文件,下载成功后双击该文件,会进入Xcode设备管理工具,在这里可以管理这些配置概要文件。
出自《》 作者:关东升&
iOS开发那些事-移动平台架构设计
低耦合企业级系统架构设计我们往往称JavaEE或.Net&开发的产品为&系统&,而移动平台(主要是:Android、iOS和Window&Phone)开发的产品为&应用&。&系统&比较复杂,需要架构设计,而&应用&相对比较简单,这是不是意味着我们不需要考虑架构问题呢?&我 们首先了解一下企业级系统架构设计。软件设计的原则是提高软件系统的&可复用性&和&可扩展性&,系统架构设计采用层次划分方式,这些层次之间是 松耦合的,层次的内部是高内聚的。降低耦合是软件设计的目标,能够设计出低耦合的系统,就意味着我们的系统具有&可复用性&和&可扩展性&。通用低耦合 JavaEE和.Net企业级系统架构图。
表示层是用户与系统交互的组件集合,用户通过这一层向系统提交请求或发出指令,系统通过这一层接收用户请求或指令,然后,将指令消化吸收后调用下一层,再将调用的结果展现到这一层。表示层应该是轻薄的不应该具有业务逻辑。业务层是系统的核心业务处理层,负责接收表示层的指令和数据,消化吸收后,进行组织业务逻辑的处理,并将结果返回给表示层。数据持久层是服务层用于访问数据库层,从设计规范上讲为了降低耦合度,服务层不应该具有访问数据库的代码,访问数据库的代码应该放到数据持久层中。信息系统层,是系统的数据来源,可以是数据库、文件、遗留系统和网络数据。
移动平台的分层架构设计移动平台的应用是缩小版本的系统,它也需要架构设计,但并非所有的应用都一定基于通用低耦合企业级系统架构,一般而言主要是涉及信息处理的应用才使用这种架构设计模式,例如:一些游戏有自己的游戏引擎,引擎也属于架构设计。iOS平台一般信息处理应用分层架构设计图。
表示层,iOS中的表示层是由UIKit&Framework构成的,它包括我们前面学习的视图、控制器、控件和事件处理等内容;业务逻辑层,采用什么框架要据具体的业务而定,但一般是具有一定业务处理功能的Objective-C和C++封装的类,或者是C封装的函数。数据持久层,提供本地或网络数据访问,它可能是访问SQLite数据API函数,也可能是CoreData技术,或是访问文件的NSFileManager,或是网络通信等技术,采用什么方式要看信息系统层是什么。信息系统层,就iOS而言它的信息来源分为:本地和网络。本地数据可以放入文件中也可以放在数据库中,目前iOS本地数据库采用SQLite3。网络可以是某个云服务,也可以是一般的Web服务。
基于同一工程的分层架 构对于我们iPhone和iPad开发有着很现实的意义。如果我们要编写一个基于iOS(iPhone和iPad两个平台)&My备忘录&应用, 它具有:增加、删除和查询备忘录的基本功能,&&备忘录&应用用例图,分层设计之后,表示层可以有不同iPhone版和iPad版本,而且业务逻辑层、数 据持久层和信息系统层都可以公用。这样可以大大减少我们的工作量,这就是分层设计的好处。
iOS考虑iPhone和iPad两个平台,我们绘制了设计原型草图,&iPhone版本的&My备忘录&应用设计原型草图。iPad版本的&My备忘录&横屏设计原型草图,&iPad版本的&My备忘录&竖屏设计原型草图。
&&在iOS平台分层的具体做法有多种模式:基于同一工程的分层、基于一个工作空间不同工程的分层和静态链接库分层。本小节介绍基于同一工程的分层。我 们在前文中已经介绍了构建自适应iPhone和iPad工程,就是我们现在要讲的基于同一工程的分层模式。请读&备忘录&应用的代码,实现过程这 里不做介绍,打开&MyNotes&工程,在Xcode工程导航面板有3个组:PresentationLayer、 BusinessLogicLayer和PersistenceLayer。创建这3个组的目的是把不同层中类放到对应的组中便于管 理,&PresentationLayer是放置的表示层相关类,BusinessLogicLayer是放置的业务逻辑层的相关 类,PersistenceLayer是放置持久层相关类。
各 个层的下面再如何划分呢?我们可以按照业务模块划分,也可以按照组件功能划分。本应用中PersistenceLayer层就还要分成dao和 domain两个组,dao是放置数据访问对象的,该对象中有对数据访问的CRUD四类方法,为了降低耦合度dao一般要设计成为协议(或Java接 口),然后根据不同的数据来源采用不同的实现方式。domain组是实体类,实体是应用中的&人&、&事&、&物&等。dao组中NoteDAO.h代码如下:@interface&NoteDAO&:&NSObject//保存数据列表@property&(nonatomic,strong)&NSMutableArray*&listD+&(NoteDAO*)sharedM//插入Note方法-(int)&create:(Note*)//删除Note方法-(int)&remove:(Note*)//修改Note方法-(int)&modify:(Note*)//查询所有数据方法-(NSMutableArray*)&findA//按照主键查询数据方法-(Note*)&findById:(Note*)@endlistData属性用于保存数据表中的数据,其中每一个元素都是Note对象,一个Note对象代表数据表中的一条数据。+&(NoteDAO*)sharedManager方法用于获得NoteDAO单例对象。dao组中NoteDAO.m代码如下:@implementation&NoteDAOstatic&NoteDAO&*sharedManager&=&+&(NoteDAO*)sharedManager{static&dispatch_once_t&dispatch_once(&once,&^{NSDateFormatter&*dateFormatter&=&[[NSDateFormatter&alloc]&init];[dateFormatter&setDateFormat:@"yyyy-MM-dd&HH:mm:ss"];NSDate&*date1&=&[dateFormatter&dateFromString:@"&16:01:03"];Note*&note1&=&[[Note&alloc]&init];note1.date&=&date1;note1.content&=&@&Welcome&to&MyNote.&;NSDate&*date2&=&[dateFormatter&dateFromString:@"&16:01:03"];Note*&note2&=&[[Note&alloc]&init];note2.date&=&date2;note2.content&=&@&欢迎使用MyNote。&;sharedManager&=&[[self&alloc]&init];sharedManager.listData&=&[[NSMutableArray&alloc]&init];[sharedManager.listData&addObject:note1];[sharedManager.listData&addObject:note2];});return&sharedM}//插入Note方法-(int)&create:(Note*)model{[self.listData&addObject:model];return&0;}&//删除Note方法-(int)&remove:(Note*)model{for&(Note*&note&in&self.listData)&{//比较日期主键是否相等if&([note.date&isEqualToDate:model.date]){[self.listData&removeObject:&note];}}return&0;}&//修改Note方法-(int)&modify:(Note*)model{for&(Note*&note&in&self.listData)&{//比较日期主键是否相等if&([note.date&isEqualToDate:model.date]){note.content&=&model.}}return&0;}&//查询所有数据方法-(NSMutableArray*)&findAll{return&self.listD}&//按照主键查询数据方法-(Note*)&findById:(Note*)model{for&(Note*&note&in&self.listData)&{//比较日期主键是否相等if&([note.date&isEqualToDate:model.date]){return&}}return&}@endNoteDAO实现采用了单例设计模式,这种设计与DAO设计模式没有关系,这主要是出于访问数据的方便。数据放置在listData属性中(本应该是从数据库中的,但是数据库访问技术我们还没有学习),CRUD方法也都是对listData的处理,而非数据库。domain组中Note代码如下,它只有两个属性date是创建备忘录的日期,content是备忘录内容:////&&Note.h&#import&&Foundation/Foundation.h&&@interface&Note&:&NSObject&@property(nonatomic,&strong)&NSDate*&@property(nonatomic,&strong)&NSString*&&@end&////&&Note.m#import&&Note.h&&@implementation&Note&@end业务逻辑层BusinessLogicLayer中的类的设计一般是按照业务模块设计的,它的方法是业务处理方法,下面代码是NoteBL.h代码:@interface&NoteBL&:&NSObject//插入Note方法-(NSMutableArray*)&createNote:(Note*)&//删除Note方法-(NSMutableArray*)&remove:(Note*)&//查询所有数据方法-(NSMutableArray*)&findA&@end在NoteBL.h中定义了三个方法,之所以定义三个方法是根据我的业务需求决定的,业务需求可以参考的用例图。下面代码是NoteBL.m代码:@implementation&NoteBL&//插入Note方法-(NSMutableArray*)&createNote:(Note*)model{NoteDAO&*dao&=&[NoteDAO&sharedManager];[dao&create:model];return&[dao&findAll];}&//删除Note方法-(NSMutableArray*)&remove:(Note*)model{NoteDAO&*dao&=&[NoteDAO&sharedManager];[dao&remove:model];return&[dao&findAll];}&//查询所有数据方法-(NSMutableArray*)&findAll{NoteDAO&*dao&=&[NoteDAO&sharedManager];return&[dao&findAll];}&@end内容来源于《》一书,作者:关东升&
iOS开放那些事-构建自适应iPhone和iPad工程
有的时候应用需要能够在iPhone和iPad上运行,当然我们可以选择做两个完全不同的工程,然后共用一些类,但是我们也可以只创建一个工程,然后编译生成一个产品,这个产品能够自适应iPhone和iPad设备,然后在App&Stroe发布的时候,它会有两套不同的截图展示给用户。App&Store上的Evernote应用,它有两套截图iPhone和iPad,这说明Evernote就是自适应iPhone和iPad设备的。&
我们来做一个名为UniversalSample的自适应iPhone和iPad设备的工程。首先,在创建时候选择Devices为&Universal&,我们以前一直选择的是iPhone,如果开发iPad专用的应用需要勾选iPad。
创建好之后生成有两套故事板,如果用nib实现也会有两套文件。
选择TARGETS,iPhone的&Main&Storyboard&(主故事板)设置的是MainStoryboard_iPhone,主故事板在应用启动时候被首先加载,它设定应用的根视图和启动的第一个画面。iPad的(主故事板),设置的是MainStoryboard_iPad。
运行时需要选择运行设备,有iPad&6.0&Simulator、iPhone&6.0&Simulator和iOS&Device(真机运行)几个选项,选择iPhone&6.0&Simulator,这说明应用要在iPhone&6.0模拟器上运行。
在编程时可以通过下面语句判断设备,常量UIUserInterfaceIdiomPhone&用于判断是否为iPhone设备,UIUserInterfaceIdiomPad用于判断是否为iPad设备。if&([[UIDevice&currentDevice]&userInterfaceIdiom]&==&UIUserInterfaceIdiomPhone)&{//&iPhone设备}&else&{//&iPad&设备}更多iOS6开放知识请参考《》本书其他内容。
想搞it,福利来了
想学iOS的,想学Andriod的,想学Java的,想学UML的,想学数据库的,想学Ajax的,想学J2ee的,来这里!,大量免费视频在线看!
智捷iOS课堂-在线课堂上线了
智捷iOS课堂-在线课堂上线了-大量免费iOS视频,注册即可观看大量iOS电子书大量Android开发知识,Android游戏开发知识大量Java,J2ee,UML,Ajax,数据库方面视频
iOS网络编程-iOS中Socket编程介绍
使用Socket进行C/S结构编程,连接过程&服 务器端监听某个端口是否有连接请求。服务器端程序处于堵塞状态,直到客户端向服务器端发出连接请求,服务器端接受请求程序才能向下运行。一旦连接建立起 来,通过Socket可以获得输入输出流对象。借助于输入输出流对象就可以实现与客户端的通讯,最后不要忘记关闭Socket和释放一些资源(包括:关闭 输入输出流)。客户端流程是先指定要通讯的服务器IP地址、端口和采用的传输协议(TCP或UDP),向服务器发出连接请求,服务器有应答请求之后,就会建立连接。之后与服务器端是一样的了。在iOS中,客户端Socket编程可以使用的技术有三种:1&使用NSStream。面向Objective-C语言的实现,由苹果提供的Foundation框架提供的API;2&使用CFStream。面向C语言的实现,由苹果提供的Core&Foundation框架提供的API;BSD&Socket。 也叫伯克利套接字(Berkeley&Socket),是Unix平台下广泛使用的Socket编程。它是面向C语言实现 的,完全使用C编写,使用起来比较麻烦。它是伯克利加州大学(University&of&California,&Berkeley)的学生开发的。在iOS中,服务器端Socket编程可以使用技术有二种:1&使用CFStream。面向C语言的实现,由苹果提供的Core&Foundation框架提供的API;2&BSD&Socket。 也叫伯克利套接字(Berkeley&Socket),是Unix平台下广泛使用的Socket编程。它是面向C语言实 现的,完全使用C编写的,使用起来比较麻烦。它是伯克利加州大学(University&of&California,&Berkeley)的学生开发 的。《iOS网络编程与云端应用最佳实践》
iOS网络编程-MBProgressHUD等待指示器
第三方的等待指示器,MBProgressHUD就是第三方提供的等待指示器框架。下面是MBProgressHUD提供的等待指示器样式,它们基 本可以分为:未知结束时间和已知结束时间两大类等待指示器,在MBProgressHUD中可以为等待指示器添加标签和详细标签&
&MBProgressHUD的下载地址是/matej/MBProgressHUD,我们将下载的源 文件中的MBProgressHUD.h和MBProgressHUD.m拷贝到自己的工程中,MBProgressHUD依赖的框架 有:Foundation.framework、UIKit.framework和CoreGraphics.framework,我们需要将这些框架添 加到工程中。我们为应用添加MBProgressHUD等待指示器,修改主视图控制器MasterViewController.m的startRequest方法代码如下,注意加粗部分:-(void)startRequest{
&&& //初始化MBProgressHUD
&&& MBProgressHUD *hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
&&& hud.mode = MBProgressHUDModeCustomV
&&& hud.labelText = @&Loading&;NSString *strURL = [[NSString alloc]initWithFormat:@&http://iosbook3/mynotes/webservice.php&];NSURL *url = [NSURL URLWithString:[strURL URLEncodedString]];NSString *if (action == ACTION_QUERY) {//查询处理post = [NSString stringWithFormat:@"email=%@&type=%@&action=%@",@"&你的用户邮箱&",@"JSON",@"query"];} else if (action == ACTION_REMOVE) {//删除处理NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];NSMutableDictionary*& dict = self.listData[indexPath.row];post = [NSString stringWithFormat:@"email=%@&type=%@&action=%@&id=%@",@"&你的用户邮箱&",@"JSON",@"remove",[dict objectForKey:@"ID"]];}NSData *postData& = [post dataUsingEncoding:NSUTF8StringEncoding];NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];[request setHTTPMethod:@"POST"];[request setHTTPBody:postData];NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self];if (connection) {_datas = [NSMutableData new];}}-(void) connection:(NSURLConnection *)connection didFailWithError: (NSError *)error {NSLog(@&%@&,[error localizedDescription]);
[MBProgressHUD hideHUDForView:self.view animated:YES];}&- (void) connectionDidFinishLoading: (NSURLConnection*) connection {NSLog(@&请求完成&&);NSDictionary* dict = [NSJSONSerialization JSONObjectWithData:_datasoptions:NSJSONReadingAllowFragments error:nil];if (action == ACTION_QUERY) {//查询处理[self reloadView:dict];} else if (action == ACTION_REMOVE) {//删除处理NSString *message = @&操作成功。&;NSNumber *resultCodeObj = [dict objectForKey:@"ResultCode"];if ([resultCodeObj integerValue] & 0) {message = [resultCodeObj errorMessage];}UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@&提示信息&message:messagedelegate:nilcancelButtonTitle:@&OK&otherButtonTitles: nil];[alertView show];//重新查询action = ACTION_QUERY;[self startRequest];}
&[MBProgressHUD hideHUDForView:self.view animated:YES];}
iOS网络编程-ASIHTTPRequest小例子-数据请求队列
实例:请求队列我们通过一个例子介绍一下请求队列使用,我们设计了一个应用,用户点击GO按钮从服务器同时下载两张图片显示在画面中。&我们直接看看主视图控制器ViewController.h代码如下:#import &ASIHTTPRequest.h&#import &ASINetworkQueue.h&#import &NSNumber+Message.h&#import &NSString+URLEncoding.h&&@interface ViewController : UIViewController&@property (weak, nonatomic) IBOutlet UIImageView *imageView1;@property (weak, nonatomic) IBOutlet UIImageView *imageView2;@property (strong) ASINetworkQueue& *networkQ&- (IBAction)onClick:(id)@end我 们需要引入ASI框架的两个头文件ASIHTTPRequest.h和ASINetworkQueue.h。其中imageView1和 imageView2是与画面对应的两个图片视图控件。还定义了ASINetworkQueue& 类型的networkQueue属性。我们直接看看主视图控制器ViewController.m中点击GO按钮调用方法,代码如下:- (IBAction)onClick:(id)sender {if (!_networkQueue) {_networkQueue = [[ASINetworkQueue alloc] init];&&&&&& &&&&&&&&&&&&&&& ①}// 停止以前的队列[_networkQueue cancelAllOperations];&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ②// 创建ASI队列[_networkQueue setDelegate:self];[_networkQueue setRequestDidFinishSelector:@selector(requestFinished:)]; &&&& ③[_networkQueue setRequestDidFailSelector:@selector(requestFailed:)]; &&&&&&&& ④[_networkQueue setQueueDidFinishSelector:@selector(queueFinished:)]; &&&&&&&& ⑤&for (int i=1; i&3; i++) {NSString *strURL = [[NSString alloc] initWithFormat:@&http://iosbook3/download.php?email=%@&FileName=test%i.jpg&,@&&你的用户邮箱&&,i];NSURL *url = [NSURL URLWithString:[strURL URLEncodedString]];ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];request.tag = &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ⑥[_networkQueue addOperation:request]; &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ⑦}[_networkQueue go];&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ⑧}我们再看看它们的回调方法,代码:- (void)requestFinished:(ASIHTTPRequest *)request{NSData *data = [request responseData];NSError *NSDictionary *resDict = [NSJSONSerialization JSONObjectWithData:dataoptions:NSJSONReadingAllowFragments error:&eror];if (!resDict) {UIImage *img = [UIImage imageWithData:data];if (request.tag ==1) {&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ①_imageView1.image =} else {_imageView2.image =}} else {NSNumber *resultCodeObj = [resDict objectForKey:@"ResultCode"];NSString *errorStr = [resultCodeObj errorMessage];UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@&错误信息&message:errorStrdelegate:nilcancelButtonTitle:@&OK&otherButtonTitles: nil];[alertView show];}if ([_networkQueue requestsCount] == 0) {&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ②[self setNetworkQueue:nil];}NSLog(@&请求成功&);}- (void)requestFailed:(ASIHTTPRequest *)request&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ③{NSError *error = [request error];NSLog(@&%@&,[error localizedDescription]);if ([_networkQueue requestsCount] == 0) {[self setNetworkQueue:nil];}NSLog(@&请求失败&);}- (void)queueFinished:(ASIHTTPRequest *)request& &&& &&&&&&&&&&&&&&&&&&&&&&& ④{if ([_networkQueue requestsCount] == 0) {[self setNetworkQueue:nil];}NSLog(@&队列完成&);}requestFinished: 方法是请求对象成功回调方法,因此有两个请求对象它会被调用两次,在第①行代码中我们根据GO按钮点击事件设定的 请求对象的tag属性,来判断是哪个请求对象的回调。进而加载到显示不同的图片视图。第②代码[_networkQueue requestsCount]可以判断队列中请求对象的个数。出自
iOS网络编程-ASIHTTPRequest异步请求
我们运行程序,如果网速很慢,查询的时候会一直黑屏,直到请求结束画面才出现,这样用户体验很不好。因此同步请求一般只是在某个子线 程中使用,而不在主线程中使用。异步请求的用户体验要比同步请求好,因此一般情况下异步请求用的很多。等待过程中在状态栏上会出现网络等待指示器的经典旋 转小图标,而使用ASIHTTPRequest异步请求就实现这些效果,不用自己额外编写代码。
ASIHTTPRequest 和ASIFormDataRequest两个请求类都可以发送异步请求,ASIFormDataRequest继承了 ASIHTTPRequest异步请求方法,所以我们重点介绍ASIHTTPRequest的异步请求。异步请求后通过回调委托对象的方 法:requestFinished:和requestFailed:实现。修改主视图控制器MasterViewController.m的 startRequest方法如下:-(void)startRequest{NSString *strURL = [[NSString alloc]initWithFormat:@&http://iosbook3/mynotes/webservice.php?email=%@&type=%@&action=%@&,@&&你的用户邮箱&&,@&JSON&,@&query&];NSURL *url = [NSURL URLWithString:[strURL URLEncodedString]];ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];[request setDelegate:self];&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ①[request startAsynchronous];&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ②}- (void)requestFinished:(ASIHTTPRequest *)request&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ③{NSData *data& = [request responseData];NSDictionary *resDict = [NSJSONSerializationJSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];[self reloadView:resDict];}- (void)requestFailed:(ASIHTTPRequest *)request&&&&& &&& &&&&&&&&&&&&&&&&&&& ④{NSError *error = [request error];NSLog(@&%@&, [error localizedDescription]);}第 ①行代码[request setDelegate:self]设置委托对象为self,然后在第②行[request startAsynchronous]发起异步请求,服务器端返回成功则回调第③行的requestFinished:方法,失败则回调第④行的 requestFailed:方法,它们的参数都是ASIHTTPRequest类型。这两个方法是默认的回调方法,我们也可以自定义回调方法。因此上面 的代码也可以改为如下形式:-(void)startRequest{& &
&&& [request setDidFinishSelector:@selector(requestSuccess:)];
&&& [request setDidFailSelector:@selector(requestError:)];[request startAsynchronous];}- (void)requestSuccess:(ASIHTTPRequest *)request{NSData *data& = [request responseData];NSDictionary *resDict = [NSJSONSerialization JSONObjectWithData:dataoptions:NSJSONReadingAllowFragments error:nil];[self reloadView:resDict];}- (void)requestError:(ASIHTTPRequest *)request{NSError *error = [request error];NSLog(@&%@&, [error localizedDescription]);}通过请求对象的setDidFinishSelector:方法指定要回调成功方法,setDidFailSelector:方法指定要回调的失败方法。在异步请求中往往为了使代码更加整洁可以使用代码块(Block),在代码块中指定回调方法。使用了代码的主视图控制器MasterViewController.m的startRequest方法如下:-(void)startRequest{NSString *strURL = [[NSString alloc] initWithFormat:@&http://iosbook3/mynotes/webservice.php?email=%@&type=%@&action=%@&,@&&你的用户邮箱&&,@&JSON&,@&query&];NSURL *url = [NSURL URLWithString:[strURL URLEncodedString]];__weak ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];&&&&&&& ①[request setCompletionBlock:^{ &&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&& &&& ②NSData *data& = [request responseData]; & &&&&&&&&&&&&&&&&&&&&&&&&&&& ③NSDictionary *resDict = [NSJSONSerialization JSONObjectWithData:dataoptions:NSJSONReadingAllowFragments error:nil];[self reloadView:resDict];}];&[request setFailedBlock:^{ &&&&&&&&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ④NSError *error = [request error];NSLog(@&%@&, [error localizedDescription]);}];[request startAsynchronous];}
iOS网络编程-ASIHTTPRequest框架同步请求
在ASIHTTPRequest框架中与HTTP请求相关的类有:ASIHTTPRequest和ASIFormDataRequest,其中最常用的是ASIHTTPRequest,ASIFormDataRequest是ASIHTTPRequest的子类,ASIFormDataRequest可以发送类似与HTML表单数据,也可以上传数据,默认采用POST请求方法。也可以其它的HTTP请求方法。它们都可以进行异步或同步请求。下面我们从最简单的GET同步请求介绍。
1、实现GET同步请求
实现GET同步请求使用最基本请求类ASIHTTPRequest就可以了。我们还是使用MyNotes应用为例,只考虑查询功能实现,修改主视图控制器MasterViewController.m的startRequest方法如下:
-(void)startRequest
NSString *strURL = [[NSString alloc] initWithFormat:
@&http://iosbook3/mynotes/webservice.php?email=%@&type=%@&action=%@&,
@&&你的用户邮箱&&,@&JSON&,@&query&];
NSURL *url = [NSURL URLWithString:[strURL URLEncodedString]];
ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];
[request startSynchronous];
NSLog(@&请求完成&&);
NSError *error = [request error];
if (!error) {
//NSString *response = [request responseString];
NSData *data& = [request responseData];
NSDictionary *resDict = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingAllowFragments error:nil];
[self reloadView:resDict];
使用ASIHTTPRequest类,需要引入头文件ASIHTTPRequest.h。
2、实现POST同步请求
发送POST方法的请求,无论同步还是异步请求都是使用ASIFormDataRequest类,只不过它们稍微有些不同。本节我们只介绍同步请求下使用ASIFormDataRequest类来发送POST方法。修改主视图控制器MasterViewController.m的startRequest方法如下:
-(void)startRequest
NSString *strURL = @&http://iosbook3/mynotes/webservice.php&;
NSURL *url = [NSURL URLWithString:[strURL URLEncodedString]];
ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
[request setPostValue:@ "&你的用户邮箱&" forKey:@"email"];&&&&&&&&&&&&&&& ③
[request setPostValue:@"JSON" forKey:@"type"];
[request setPostValue:@"query" forKey:@"action"];
[request startSynchronous];
NSLog(@&请求完成&&);
NSError *error = [request error];
if (!error) {
//NSString *response = [request responseString];
NSData *data& = [request responseData];
NSDictionary *resDict = [NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingAllowFragments error:nil];
[self reloadView:resDict];
使用ASIFormDataRequest需要引入头文件ASIFormDataRequest.h。
如果我们想发送除了GET和POST以外的其它请求方法,可以使用[request setRequestMethod:@"PUT"]语句设置,其中PUT是请求方法。
iOS网络编程--ASIHTTPRequest框架安装和配置-图文解说
ASIHTTPRequest框架是优秀的第三方Objective-C的HTTP框架,支持Mac OS X和iOS下的HTTP开发。技术支持网站是/ASIHTTPRequest/。具有如下优点: 支持下载数据放在内存或本地文件 容易访问请求和应答HTTP header 支持Cookie 支持GZIP请求或应答 支持缓存 支持同步或异步请求 支持HTTPS 但ASIHTTPRequest框架不支持ARC,如果在ARC下开发配置起来有点麻烦。本章我们介绍的实例是基于ARC下开发的。
安装和配置ASIHTTPRequest框架
首先下载地址/pokeb/asi-http-request/tree,下载完成打开asi-http-request目录,选择文件添加到我们的iOS工程中。
然后我们还需要为工程添加一些支持的类库或框架,它们包括:
CFNetwork.framework SystemConfiguration.framework MobileCoreServices.framework CoreGraphics.framework
libz.dylib 选择工程的Targets(编号①所示),再选择Build Phases(编号②所示),然后再选择编号③,弹出对话框,在对话框中选择上面的框架或类库。最后点击编号④所示的Add按钮添加。
这样ASIHTTPRequest框架所需要的类库和框架就添加进来了。然后我们可以编译一下,看看是否有什么错误。如果我们的工程采用ARC(自动引用计数)管理内存的话,就会有些小麻烦,会有编译错误。
这些编译错误不能难看出是ARC的不支持错误,这是由于ASIHTTPRequest框架本身不支持ARC技术,它的源代码中使用了MRC(手动管理引用 计数)。解决方法是为ASIHTTPRequest框架中的这些源程序文件,设置不采用ARC编译,编译参数是为-fno-objc-arc。选择工程的 Targets(编号①所示),再选择Build Phases(编号②所示),然后再选择ASIHTTPRequest中的文件,双击弹出对话框,在对话框中输入&-fno-objc-arc&。
iOS开发那些事-iOS网络编程同步GET方法请求编程
iOS SDK为HTTP请求提供了同步和异步请求两种不同的API,而且可以使用GET或POST等请求方法。我们先了解其中最为简单的同步GET方法请求。为了学习这些API的使用我们还是选择第3章MyNotes&备忘录&应用实例,与第3章不同的是数据来源于服务器端,而不是本地的Notes.xml(或Notes.json)文件。首先实现查询业务,查询业务请求可以在主视图控制器MasterViewController类中实现,其中MasterViewController.h代码如下:#import &UIKit/UIKit.h&#import &NSString+URLEncoding.h&#import &NSNumber+Message.h&&@interface MasterViewController : UITableViewController&@property (strong, nonatomic) DetailViewController *detailViewC//保存数据列表@property (nonatomic,strong) NSMutableArray* listD&//重新加载表视图-(void)reloadView:(NSDictionary*)&//开始请求Web Service-(void)startR&@end其中引入头文件NSString+URLEncoding.h文件是在程序中需要对URL进行编码处理。引入头文件 NSNumber+Message.h文件是处理把服务器返回消息代码转换为用户能看懂的消息。MasterViewController.m中的主要代 码如下:- (void)viewDidLoad{[super viewDidLoad];self.navigationItem.leftBarButtonItem = self.editButtonIself.detailViewController &= (DetailViewController *)[[self.splitViewController.viewControllers lastObject] topViewController];[self startRequest]; &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ①}&#pragma mark & Table View- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {return 1;}&- (NSInteger)tableView:(UITableView *)tableViewnumberOfRowsInSection:(NSInteger)section {return self.listData.}&- (UITableViewCell *)tableView:(UITableView *)tableViewcellForRowAtIndexPath:(NSIndexPath *)indexPath {UITableViewCell *cell= [tableView dequeueReusableCellWithIdentifier:@"Cell"forIndexPath:indexPath];NSMutableDictionary*& dict = self.listData[indexPath.row];cell.textLabel.text = [dict objectForKey:@"Content"];cell.detailTextLabel.text = [dict objectForKey:@"CDate"];}其中第①行代码[self startRequest]调用自己的方法startRequest实现请求Web Service。MasterViewController.m中的startRequest方法代码如下:/** 开始请求Web Service*/-(void)startRequest{NSString *strURL = [[NSString alloc] initWithFormat:@&http://iosbook3/mynotes/webservice.php?email=%@&type=%@&action=%@&,@&&你的用户邮箱&&,@&JSON&,@&query&];&&&&&&&&&&&&&&&&&& &&&&&&& ①NSURL *url = [NSURL URLWithString:[strURL URLEncodedString]];&&&&&&&&&&&& ②NSURLRequest *request = [[NSURLRequest alloc] initWithURL:url];&&&&&&&&&&&&&& ③NSData *data& = [NSURLConnection sendSynchronousRequest:requestreturningResponse:nil error:nil];&&&&&& &&&&&&&&&&&&&&& ④NSLog(@&请求完成&&);NSDictionary *resDict = [NSJSONSerialization JSONObjectWithData:dataoptions:NSJSONReadingAllowFragments error:nil];[self reloadView:resDict]; &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ⑤}此外,我们在前文中还提到了一个分类NSString (URLEncoding),它的作用是对URL编码和解码,它的代码如下:@interface NSString (URLEncoding)&-(NSString *)URLEncodedS-(NSString *)URLDecodedS&@end&@implementation NSString (URLEncoding)&- (NSString *)URLEncodedString{NSString *result = (NSString *)CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,①(CFStringRef)self,NULL, &&&&&&&&&&&&&&&&& &&& &&& ②CFSTR(&+$,#[] &),&&&&& &&& &&& &&& &&& ③kCFStringEncodingUTF8));}- (NSString*)URLDecodedString{NSString *result = (NSString *)CFBridgingRelease(CFURLCreateStringByReplacingPercentEscapesUsingEncoding(kCFAllocatorDefault, &&&&&&& &&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&& ③(CFStringRef)self, CFSTR(&&),&&&&&&&&&&&&&&&&&&&&&& &&&&&&&&&&&&&&& ④kCFStringEncodingUTF8));}@end第①行代码CFURLCreateStringByAddingPercentEscape函数是Core Foundation框架提供的C函数,可以把内容转换成为URL编码。第②行参数指定了将本身为非法URL字符不进行编码的字符集合,例如:&!* ()&等符号。第③行参数是将本身为合法URL字符需要进行编码的字符集合。第③行代码CFURLCreateStringByReplacingPercentEscapesUsingEncoding函数是Core Foundation框架提供的C函数,它与上面CFURLCreateStringByAddingPercentEscape函数截然相反,是进行 URL解码的。第④行的参数指定不进行解码的字符集。Foundation框架也提供了基于Objective-C的方法进行URL编码和解码,与 CFURLCreateStringByAddingPercentEscape函数对应的NSString方法是 stringByAddingPercentEscapesUsingEncoding。与 CFURLCreateStringByReplacingPercentEscapesUsingEncoding函数对应的NSString方法是 stringByReplacingPercentEscapesUsingEncoding:,由于这些方法不能自定义是否要编码和解码的字符集,因此 没有上面的函数灵活。
iOS开发那些事-Git在Xcode中的配置与使用常见问题总结
书接上回提出的Git在Xcode中的配置与使用常见问题4个问题&问题1,如何在Xcode中创建代码库,并添加和提交代码到代码库?问题2,如何在Xcode中提交推送给远程服务器代码库?问题3,如何在Xcode中克隆远程服务器代码库到本地?问题4,如何使用Xcode获取远程代码库数据,并解决冲突问题?&1、问题1创建代码库有两种方式,一种是新建工程时候创建,另一种是把现有的工程拷贝到代码库下,再初始化代码库。如果是新建工程时候创建,在保存文件时候可以选择是否创建,如果勾选&Create local git repository for this project&,则就会为工程创建代码库。&注意Xcode 4生成的目录结构如下:1& HelloWorld2 ├── HelloWorld3 │&& ├── &4 │&& ├── ViewController.h5 │&& ├── ViewController.m6 │&& ├── en.lproj7 │&& │&& ├── InfoPlist.strings8 │&& │&& └── MainStoryboard.storyboard9 │&& └── main.m10└── HelloWorld.xcodeproj11│12└──.git第一行的HelloWorld是工程目录也是代码库的根目录,第二行的HelloWorld目录是存放源程序目录。而我们以前的目录结构与此不同,目录结构如下所示:1& myrepo2└── HelloWorld3│&& ├── HelloWorld4│& &│&& ├── &5│&& │&& ├── ViewController.m6│&& │&& └── main.m7│&& └── HelloWorld.xcodeproj8└──.git第一行myrepo是代码库的根目录,第二行的HelloWorld是工程目录,这样的结构可以一个代码库可以放置多个工程,是一对多的关系,而Xcode生成的方式是代码库就是工程目录,它们是一对一的关系。如果我们还是采用一对多的关系,就不用在创建工程的时候勾选&Create local git repository for this project&选项了。这就需要将现有的HelloWorld工程拷贝到myrepo目录,在终端中执行如下命令:$ cd ~/myrepo$ git initInitialized empty Git repository in& ~/.git/初始化完成之后在添加并提交HelloWorld工程,在终端中执行如下命令:$ git add .$ git commit -m &tony init&[master (root-commit) 98d7e4a] tony init10 files changed, 643 insertions(+)create mode 100644 HelloWorld/HelloWorld.xcodeproj/project.pbxprojcreate mode 100644 HelloWorld/HelloWorld/AppDelegate.hcreate mode 100644 HelloWorld/HelloWorld/AppDelegate.mcreate mode 100644 HelloWorld/HelloWorld/HelloWorld-Info.plistcreate mode 100644 HelloWorld/HelloWorld/HelloWorld-Prefix.pchcreate mode 100644 HelloWorld/HelloWorld/ViewController.hcreate mode 100644 HelloWorld/HelloWorld/ViewController.mcreate mode 100644 HelloWorld/HelloWorld/en.lproj/InfoPlist.stringscreate mode 100644 HelloWorld/HelloWorld/en.lproj/ViewController.xibcreate mode 100644 HelloWorld/HelloWorld/main.m然后就可以在Xcode中代码这个工程了。我们修改并保存文件后,会看到在导航面板中文件的后面有一个&M&图标,这说明文件修改了但没有提交。&如 果只是想提交选中的文件,可以是右键菜单Source Control&Commit Selected Files&,其中的Source Control菜单都是有关代码控制的。如果想提交全部的修改文件,可以菜单File&Source Control&Commit&。然后会弹出对话框。&其中有两个代码窗口,左边是本地未提交版本,右边是代码库中的版本,这里可以比较看看修改了哪些内容。在下面输入框中添加注释,点击提交按钮就可以提交了。2、问题2本地有代码库提交推送给远程服务器代码库,在Xcode中可以通过菜单File&Source Control&Push&进行推送,但是如果是第一次访问,会出现对话框,没有可以推送的远程服务器代码库名。&我 们需要建立这个名字,在命令行中我们是通过$ git remote add hw git@192.168.1.108:myrepo创建的,其中hw就是这个名字。在Xcode中可以通过菜单Window & Organizer,选中Repositories&myrepo&Remotes,点击左下角的&Add Remote&按钮,弹出对话框,在Remote Name项目中输入remote_repo,Location项目中输入git@192.168.1.108:myrepo,完成之后点击Create按 钮创建这个名字。&创建完成再重新推送,如果弹出对话框,Push按钮是可以点击的,点击Push按钮推送。&3、问题3这 个问题是从服务器代码库克隆到本地,首先需要在Xcode中添加一个远程代码库,需要通过菜单Window & Organizer进入到Repositories画面,点选左下角的&+&按钮,选择Add Repository,在Location项目中输入git@192.168.1.108,Type项目选择Git,Name项目会自动添加,如果 Authentication required为变为黄色小点,说明配置连接没有问题,然后点击Add按钮创建。
如果创建成功,就会出现在左边代码库列表中,请选择刚才创建的代码库,然后选择下面的Clone按钮,并选择本地保存位置。&4、问题4如果服务器代码有新的版本,获取远程代码库数据到本地,可以通过菜单File&Source Control&Pull&。然后会弹出对话框。选择Choose按钮就可以获取新的版本了。
如果这个过程中有冲突发生,会弹出对话框在两个代码窗口中可以看到它们的冲突点,
下面的4个按钮,可以把冲突点进行合并,并进行编辑。如果没有冲突,Pull是可以点击,点击Pull按钮就可以了。
iOS开发那些事-Git在Xcode中的配置与使用
很多Git命令都是在命令行下运行的,命令行下管理Git有很多优点不用多说。但最大的缺点是要求用户记住这些命令。因此Git图形界面还是很受一 些用户欢迎的,其中Xcode作为集成开发环境工具,也提供了一定Git图形界面功能。但是要想在Xcode中使用Git管理工程代码还想需要进行一些配 置,然后才能使用。如果我们是使用Xcode 4创建的一个iOS工程,在终端的命令行中提交代码时候,可能会出现下面的部分信息:create mode 100644 HelloWorld/HelloWorld.xcodeproj/project.xcworkspace/contents.xcworkspacedatacreate mode 100644 HelloWorld/HelloWorld.xcodeproj/project.xcworkspace/xcuserdata/tonyguan.xcuserdatad/UserInterfaceState.xcuserstatecreate mode 100644 HelloWorld/HelloWorld.xcodeproj/xcuserdata/tonyguan.xcuserdatad/xcschemes/HelloWorld.xcschemecreate mode 100644 HelloWorld/HelloWorld.xcodeproj/xcuserdata/tonyguan.xcuserdatad/xcschemes/xcschememanagement.plistrewrite HelloWorld.xcodeproj/project.xcworkspace/xcuserdata/tonyguan.xcuserdatad/UserInterfaceState.xcuserstate (83%)事实上是能够列入到代码版本控制的文件是有规定的,不能是编写的二进制文件、临时文件和用户特有的文件等。下面是Xcode 4创建的HelloWorld工程的目录结果:HelloWorld├── HelloWorld│&& ├── AppDelegate.h│&& ├── AppDelegate.m│&& ├── HelloWorld-Info.plist│&& ├── HelloWorld-Prefix.pch│&& ├── ViewController.h│&& ├── ViewController.m│&& ├── en.lproj│&& │&& ├── InfoPlist.strings│&& │&& └── ViewController.xib│&& └── main.m└── HelloWorld.xcodeproj├── project.pbxproj├── project.xcworkspace│&& ├── contents.xcworkspacedata│&& └── xcuserdata│&&&&&& └── tonyguan.xcuserdatad│&&&&&&&&&& └── UserInterfaceState.xcuserstate└── xcuserdata└── tonyguan.xcuserdatad├── xcdebugger│&& └── Breakpoints.xcbkptlist└── xcschemes├── HelloWorld.xcscheme└── xcschememanagement.plist其中HelloWorld.xcodeproj属于包文件,它内部的很多东西是不能提交的,包括:project.xcworkspace和 xcuserdata,它们是与用户有关的。Git中有一个.gitignore配置文件,在这个文件中可以设置被忽略的文件。下面的内容是一 个.gitignore配置文件:# Exclude the build directorybuild/*# Exclude temp nibs and swap files*~.nib*.swp# Exclude OS X folder attributes.DS_Store# Exclude user-specific XCode 3 and 4 files*.mode1*.mode1v3*.mode2v3*.perspective*.perspectivev3*.pbxuser*.xcworkspacexcuserdata文件中#号是注释,可以使用正则表达式,文件考虑到了X code 3和4差别。这个文件创建之后,应该放在什么地方?如果只考虑对一个特定工程忽略,.gitignore文件应该放在代码库目录下面,目录结构如下所示:&代码库目录&└── HelloWorld├── HelloWorld│&& ├── AppDelegate.h│&& ├── AppDelegate.m│&& ├── Default-568h@2x.png│&& ├── Default.png│&& ├── Default@2x.png│&& ├── ViewController.h│&& ├── ViewController.m│&& ├── HelloWorld-Info.plist│&& ├── HelloWorld-Prefix.pch│&& ├── en.lproj│&& │&& ├── InfoPlist.strings│&& │&& └── MainStoryboard.storyboard│&& └── main.m└── HelloWorld.xcodeproj│└── .gitignore如果考虑适用于所有的Xcode工程,则需要使用git config命令配置git,在终端中执行git config命令:
$ git config &global core.excludesfile &~/.gitignore该命令会将配置信息写入到~/.gitconfig文件中,&global参数是配置全局信息,~/.gitignore说明文件是放置于当前用户目录下。为了使本机上的所有代码库都默认使用git用户,还需要执行如下命令进行配置:
$ git config &global user.name git
$ git config &global user.email 在Xcode中使用git还会遇到很多问题,老关总结常见的4个问题,明天和大家分享一下,得干活去了问题1,如何在Xcode中创建代码库,并添加和提交代码到代码库?问题2,如何在Xcode中提交推送给远程服务器代码库?问题3,如何在Xcode中克隆远程服务器代码库到本地?问题4,如何使用Xcode获取远程代码库数据,并解决冲突问题?
iOS开发那些事-平铺导航–基于分屏导航及案例实现
平铺导航模式是非常重要的导航模式。一般用于简单的扁平化信息浏览或任务。扁平化信息是指这些信息之间没有从属的层次关系,如中国的城市中北京、上 海和哈尔滨之间是扁平化信息,而哈尔滨市与黑龙江省之间的关系是从属的层次关系,层次关系信息可以采用标签导航和树形结构导航。从一个案例开始介绍平铺导航。如果我想为开发一个基于iPhone的&画廊&应用,目前只有3幅名画(左图是毕加索-哭泣、中图是达芬奇-蒙娜丽莎、右图是罗丹-思想者)收录到应用中。由于这3幅名画之间没有层次关系,他们之间是扁平的。
基于分屏导航实现基于分屏导航是平铺导航模式的主要实现方式,主要涉及的控件有:分屏控件(UIPageControl)和ScrollView,分屏控件是iOS标准控件。基 于分屏导航的手势有两种,一个是点击小点的左边(上边)或右边(下边)实现翻屏,另一个是用手在屏幕上滑动实现翻屏。屏幕的总数应该限制在20个 以内,超过20个分屏控件的小点就会溢出。事实上,如果一个应用超过10屏,此时使用基于分屏导航的平铺导航模式已经不是很方便了。下面我 们采用基于分屏导航模式实现&画廊&应用。使用Single View Application模板创建一个名为PageControlNavigation的工程。将ScrollView和PageControl控件拖曳到 设计界面,将其摆放到合适的位置,通过属性将视图背景设置为黑色。&在Interface Builder中选中ScrollView控件,打开其属性检查器,设置Scrollers中的属性,此时该ScrollView控件不显示水平和垂直滚动条,但可以滚动也可以分屏。&在Interface Builder中选中PageControl控件,打开其属性检查器,设置Pages中&# of Pages&(总屏数)属性为3,Current(当前屏)属性为0。再打开尺寸检查器,修改Width(宽度)属性为200,将这个属性设置大一些是为 了便于手指点击。
&最后,还需要为这两个控件定义输出口并连线,而且要为分屏控件控件定义响应屏幕变化事件的方法changePage:并连线。完成之后,ViewController.h文件中增加的代码如下:@property (weak, nonatomic) IBOutlet UIScrollView *scrollV@property (weak, nonatomic) IBOutlet UIPageControl *pageC- (IBAction)changePage:(id)下面设计3个视图,将3个View Controller视图控制器拖曳到MainStoryboard.storyboard的设计界面中,然后再并分别拖曳3个ImageView到3个不同视图上。
然后再分别修改3个ImageView的Image属性为名画的文件名。
设 置完成ImageView的Image属性后,再依次选中视图控制器,将Storyboard ID分别修改为page1、page2、page3。与模态视图的例子不同,我们不需要再创建视图控制器的子类。就本例而言,我们只需展示一些图片。如果 需要处理动作事件,则需要自定义视图控制器的子类。设计完成后,我们看看程序代码ViewController.h:#import &UIKit/UIKit.h&@interface ViewController : UIViewController &UIScrollViewDelegate&@property (strong, nonatomic) UIView *page1;@property (strong, nonatomic) UIView *page2;@property (strong, nonatomic) UIView *page3;@property (weak, nonatomic) IBOutlet UIScrollView *scrollV@property (weak, nonatomic) IBOutlet UIPageControl *pageC- (IBAction)changePage:(id)@end由于需要响应UIScrollView的事件,我们在ViewController中实现了UIScrollViewDelegate协议。下面我们看看ViewController.m中viewDidLoad方法的代码:- (void)viewDidLoad{[super viewDidLoad];// Do any additional setup after loading the view, typically from a nib.self.scrollView.contentSize& = CGSizeMake(self.view.frame.size.width*3, self.scrollView.frame.size.height);self.scrollView.frame = self.view.UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:@"MainStoryboard" bundle:nil];UIViewController* page1ViewController = [mainStoryboard instantiateViewControllerWithIdentifier:@"page1"];self.page1 = page1ViewController.self.page1.frame = CGRectMake(0.0f, 0.0f, 320.0f, 420.0f);UIViewController* page2ViewController = [mainStoryboard instantiateViewControllerWithIdentifier:@"page2"];self.page2 = page2ViewController.self.page2.frame = CGRectMake(320.0f, 0.0f, 320.0f, 420.0f);UIViewController* page3ViewController = [mainStoryboard instantiateViewControllerWithIdentifier:@"page3"];self.page3 = page3ViewController.self.page3.frame = CGRectMake(2 * 320.0f, 0.0f, 320.0f, 420.0f);self.scrollView.delegate =[self.scrollView addSubview:self.page1];[self.scrollView addSubview:self.page2];[self.scrollView addSubview:self.page3];}该 方法主要进行控件初始化,由于需要计算各个控件的位置,代码比较多,但是基本上没什么难点。self.scrollView.delegate = self是把当前视图控制(UIScrollViewDelegate实现对象)分配给ScrollView控件,以便响应事件处理,其他事件是 scrollViewDidScroll:,其代码如下:- (void) scrollViewDidScroll: (UIScrollView *) aScrollView{CGPoint offset = aScrollView.contentOself.pageControl.currentPage = offset.x / 320.0f;}当左右滑动屏幕,ScrollView控件滚动完成的时候,要计算和设定分屏控件的当前屏currentPage。当点击分屏控件时屏幕发生变化,此时触发changePage:方法,其代码如下:- (IBAction)changePage:(id)sender{[UIView animateWithDuration:0.3f animations:^{int whichPage = self.pageControl.currentPself.scrollView.contentOffset = CGPointMake(320.0f * whichPage, 0.0f);}];}在 上述代码中,我们根据分屏控件当前屏幕属性(currentPage)重新调整了ScrollView控件的偏移量,而且为了使屏幕变化产生动画 效果,使用了[UIView animateWithDuration:0.3f animations:^{ &}]代码,重新调整ScrollView控件偏移量。运行代码,得到的效果&
iOS开发那些事--自定义单元格实现
自定义单元格当苹果公司提供给的单元格样式不能我们的业务需求的时候,我们需要自定义单元格。在iOS 5之前,自定义单元格可以有两种实现方式:代码实现和用xib技术实现。用xib技术实现相对比较简单,创建一个xib文件,然后定义一个继承 UITableViewCell类单元格类即可。在iOS 5之后我们又有了新的选择,故事板实现方式,这种方式比xib方式更简单一些。&我们把简单表视图案例的原型图修改一下,这种情况下四种内置的单元格样式就不合适了。& &&& 采用&Single View Application&工程模版创建一个名为&CustomCell&的工程,Table View属性的&Prototype Cells&项目设为1(除此之外其它的操作过程与上同)。&设计画面中上部会有一个单元格设计画面,我们可以在这个位置进行单元格布局的设计。从对象库拖拽一个Label和Image View到单元格设计画面,调整好它们的位置。&创建自定义单元格类CustomCell, 选择UITableViewCell为父类&再 回到IB设计画面,在IB中左边选择&Table View Controller Scene& & &Table View Controller& & &Table View& & &Table View Cell&,打开单元格的标识检查器,在Class的选项中选择CustomCell类。&为Lable和ImageView控件连接输出口&本案例的代码如下:////& CustomCell.h//& CustomCell#import &UIKit/UIKit.h&@interface CustomCell : UITableViewCell@property (weak, nonatomic) IBOutlet UILabel *@property (weak, nonatomic) IBOutlet UIImageView *@end////& CustomCell.m//& CustomCell#import &CustomCell.h&@implementation CustomCell@endCustomCell类的代码比较简单,在有些业务中还需要定义动作。修改视图控制器ViewController.m中的tableView: cellForRowAtIndexPath:方法,代码如下:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{static NSString *CellIdentifier = @&Cell&;CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
&&& if (cell == nil) {
&&&&&&& cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
&&& } NSUInteger row = [indexPath row];NSDictionary *rowDict = [self.listTeams objectAtIndex:row];cell.name.text =& [rowDict objectForKey:@"name"];cell.image.image = [UIImage imageNamed:[rowDict objectForKey:@"image"]];NSUInteger row = [indexPath row];NSDictionary *rowDict = [self.listFilterTeams objectAtIndex:row];cell.textLabel.text =& [rowDict objectForKey:@"name"];NSString *imagePath = [rowDict objectForKey:@"image"];imagePath = [imagePath stringByAppendingString:@".png"];cell.image.image = [UIImage imageNamed:imagePath];cell.accessoryType = UITableViewCellAccessoryDisclosureI}我们看到if (cell == nil){}代码被移除,这是因为我们在IB中已经将重用标识设定为Cell了。 方法中的其它代码与简单表一致,此处不再赘述。运行一下。
iOS开发那些事--简单表视图
表视图是iOS开发中使用最频繁的视图,我们一般都会选择以表的形式来展现数据,比如通讯录、频道列表等。表视图分段、分组、索引等功能使我们所展 示的数据看起来更规整更有调理,更令人兴奋的是表视图还可以利用细节展示等功能多层次的展示数据,正所谓一表胜千言。 不过,相较于其它控件表视图的使用比较复杂,但是对比于表视图各种灵活多变的功能,我们在使用上花费的努力还是相当值得的。&
简单表视图表视图的形式灵活多变,本着由浅入深的原则,我们先从简单表视图开始学习。本节讲的简单表视图是动态表,(iOS 5之前全部是动态表没有动态表和静态表区别)。创建简单表视图在iOS 5之后我们可以使用xib或者故事板技术创建表视图,要显示的是一个最基本的表,我们只需实现UITableViewDataSource协议中必须要实 现的方法即可,分别是tableView:numberOfRowsInSection:和 tableView:cellForRowAtIndexPath:就可以了。:
构造方法initWithFrame:style:是在实例化表视图的时候调用,如果采用xib或故事板来设计表视图,那么表视图的创建是在实例化 表视图控制器的时候完成的,表视图显示的时候会发出tableView:numberOfRowsInSection:消息询问当前节中的行数,表视图单 元格显示的时候会发出tableView:cellForRowAtIndexPath:消息为单元格提供显示数据。我们创建一个简单表视图,单元格使用默认样式,有图标和主标题,显示的是世界杯球队的信息。&使用&Single View Application&模板创建一个工程,工程名为&SimpleTable&,打开IB设计画面,在&View Controller Scene&选中&View Controller&删除控制器,然后从控件库中拖拽一个&Table View Controller&到设计画面。&将h文件中ViewController的父类从原来的UIViewController修改为UITableViewController。在IB设计画面左侧的Scene列表中选择&Table View Controller Scene& & &Table View Controller&, 打开表视图控制器的标识检查器,在Class选项里选择&ViewController&,这是我们自己的编写视图控制器。
然后在Scene列表中选择&Table View Controller Scene& & &Table View Controller& & &Table View&, 打开表视图的属性检查器。Content下有两个选项&Dynamic Prototypes&和&Static Cells&,这两个选项只有在故事板中才有。&Dynamic Prototypes&是构建&动态表&
如果通过代码来实现单元格的创建,&Prototype Cells&项目要设为0,代码实现的模式代码如下:static NSString *CellIdentifier = @&CellIdentifier&;UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];}Identifier是可重用单元格标识符,这个可重用单元格与Collection视图中的可重用单元格概念一样。首先,在表视图中查找是否有可 以重用的单元格,如果没有就通过initWithStyle: reuseIdentifier:构造方法创建一个单元格对象。如果要利用故事板设计单元格,要选择&Table View Controller Scene& & &Table View Controller& & &Table View& & &Table View Cell&,打开单元格的属性检查器,Style下有很多选项, Identifier是指可重用单元格标识符。&这样操作以后在代码部分就不需要实例化单元格了,我们直接通过设定的Identifier取得单元格的实例,以此达到重用单元格的目的。static NSString *CellIdentifier = @&CellIdentifier&;UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
&&& if (cell == nil) {
&&&&&&& cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
&&& }我们需要将&team.plist&和&球队图片&添加到工程中,ViewController.h文件的代码如下:#import &UIKit/UIKit.h&@interface ViewController : UITableViewController@property (nonatomic, strong) NSArray *listT@end需要将ViewController的父类修改为UITableViewController。还定义NSArray*类型的属性 listTeams,listTeams用来装载从文件中读取的数据。读取属性列表文件team.plist的操作是在viewDidLoad方法中实现 的&ViewController.m文件的viewDidLoad方法代码如下:- (void)viewDidLoad{[super viewDidLoad];NSBundle *bundle = [NSBundle mainBundle];NSString *plistPath = [bundle pathForResource:@"team" ofType:@"plist"];//获取属性列表文件中的全部数据self.listTeams = [[NSArray alloc] initWithContentsOfFile:plistPath];}我们再看看UITableViewDataSource协议方法,代码如下:- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{return [self.listTeams count];}- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{static NSString *CellIdentifier = @&CellIdentifier&;UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];if (cell == nil) {cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];}NSUInteger row = [indexPath row];NSDictionary *rowDict = [self.listFilterTeams objectAtIndex:row];cell.textLabel.text =& [rowDict objectForKey:@"name"];NSString *imagePath = [rowDict objectForKey:@"image"];imagePath = [imagePath stringByAppendingString:@".png"];cell.imageView.image = [UIImage imageNamed:imagePath];cell.accessoryType = UITableViewCellAccessoryDisclosureI}由于当前的这个表事实上只有一个节,因此不需要对节进行区分,在tableView: numberOfRowsInSection:方法中直接返回listTeams属性的长度即可。 tableView:cellForRowAtIndexPath:方法中NSIndexPath参数的row方法可以获得当前的单元格行索引。 cell.accessoryType属性是设置扩展视图类型。我们可以将单元格的样式UITableViewCellStyleDefault替换为其它三种,来体验一下其它的三种单元格样式的效果。
简单表案例运行结果
iOS开发那些事-iOS常用设计模式–委托模式案例实现
书接上回,应用案例我们以UITextFieldDelegate为例来说明一下委托的使用。 UITextFieldDelegate是控件UITextField的 委托,控件的委托主要负责响应控件事件或控制其他对象。除了UITextField,WebView、UITableView等控件也有相应的委托对象。打开UITextFieldDelegate的API文档,其中有4个有关编辑的方法,还要3个其它方法。
这里我们在编辑过程中消息的发送,UITextField编辑过程中与UITextFieldDelegate委托对象之间交互过程。
在 文本框编辑开始前后会发出消息textFieldShouldBeginEditing:和 textFieldDidBeginEditing:,编辑结束前后会发出消息textFieldShouldEndEditing:和 textFieldDidEndEditing:。为了演示文本框编辑前后发生了什么,我们需要编写一个简单的文本框工程,画面中只有一个文本框。
我们在视图控制器ViewController中实现UITextFieldDelegate,ViewController是UITextField的委托对象。ViewController.h代码如下:#import &UIKit/UIKit.h&@interface ViewController : UIViewController&UITextFieldDelegate&@property (weak, nonatomic) IBOutlet UITextField *textF@endh文件中ViewController实现了UITextFieldDelegate协议,把UITextField 定义为一个弱引用的&输出口&(&输出口&概念我们将在UIView与控件一章详细介绍)。ViewController.m代码如下:@implementation ViewController- (void)viewDidLoad{&&& [super viewDidLoad];&&& self.textField.delegate =}#pragma mark & UITextFieldDelegate method- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{&&& NSLog(@&call textFieldShouldBeginEditing:&);&&& return YES;}- (void)textFieldDidBeginEditing:(UITextField *)textField{&&& NSLog(@&call textFieldDidBeginEditing:&);}- (BOOL)textFieldShouldEndEditing:(UITextField *)textField{&&& NSLog(@&call textFieldShouldEndEditing:&);&&& return YES;}- (void)textFieldDidEndEditing:(UITextField *)textField{&&& NSLog(@&call textFieldDidEndEditing:&);}- (BOOL)textFieldShouldReturn:(UITextField *)textField{&&& NSLog(@&call textFieldShouldReturn:&);&&& [textField resignFirstResponder];&&& return YES;}@end在 m文件中viewDidLoad 方法self.textField.delegate = self语句极为重要,它将委托对象ViewController分配给文本框对象,除了通过代码我们也可以通过IB工具进行连线分配。打开故事板文件, 右键点击文本框控件,弹出菜单,用鼠标拖拽位于Outlets(输出口)下面的delegate后面的圆圈,到View Controller上松开鼠标。
这样运行代码,当触摸文本框使其处于编辑状态时,在日志中会输出:call textFieldShouldBeginEditing:call textFieldDidBeginEditing:输入完成点击&return&键关闭键盘,结束编辑状态,日志中输出:call textFieldShouldReturn:call textFieldShouldEndEditing:call textFieldDidEndEditing:textFieldShouldReturn:是点击&return&键发出的消息。我们借助于该消息通过[textField resignFirstResponder]方法关闭键盘。更 复杂的控件(如UITableView)除了委托协议(UITableViewDelegate)还有 数据源协议(UITableViewDataSource)。数据源与委托一样都是委托设计模式的具应用,委托对象主要对控件对象的事件和状态变化做出响 应,而数据源对象是为控件对象提供数据。需要注意的是委托中的方法在实现时是可选的,而数据源中的方法一般必须实现。
iOS开发那些事-iOS常用设计模式–委托模式
对于iOS开发,举例Cocoa框架下的几个设计模式为大家分析。当然,Cocoa框架下关于设计模式的内容远远不止这些,我们选择了常用的几种:单例模式、委托模式、观察者模式、MVC模式。&委托模式委托模式从GoF 设计装饰(Decorator)、适配器(Adapter)和模板方法(Template Method)等模式演变而来。几乎每一个应用都会或多或少地使用到委托模式。不只是CocoaTouch框架,在Cocoa框架中委托模式也得到了广泛的应用。问题提出
对于应用生命周期的非运行状态&&应用启动场景,我们把从点击图标到第一个画面启动的过程细化了一下假设上图这一系列的处理,都是在一个上帝类UIApplication完成的。之所以叫&上帝类(God Class)&,是因为它&无所不能&、&包含所有&。 在面向对象的软件设计中&上帝类&不是很友好, 需要重构。在编程过程中要尽量避免上帝类的使用,因为上帝类是高耦合的,职责不清,所以难以维护。我们需要&去除上帝类&,把看似功能很强且很难维护的 类,按照职责把自己的属性或方法分派到各自的类中或分解成功能明确的类,从而去掉&上帝类&。幸运的是苹果没有把UIApplication类设计成&上帝类&,苹果处理分割到两个不同的角色类中,其中一个扮演框架类角色,框架类具有通用、 可重复使用、与具体应用无关等特点。另一个扮演应用相关类的角色,应用相关类与具体应用有关,由于要受到框架类的控制,常常被设计成为&协议&,在 Java中称之为&接口&。开发人员需要在具体的应用中实现这个&协议&。将application:didFinishLaunchingWithOptions:和 applicationDidBecomeActive:完成功能提取出来,定义在UIApplicationDelegate协议中,这样 UIApplication类就变成了框架类。
在具体使用时候需要实现UIApplicationDelegate协议,HelloWorld应用的类图。UIApplication不直接依赖 于AppDelegate类,而是依赖于UIApplicationDelegate协议,这在面向对象软件设计原则中叫做&面向接口的编程&。 AppDelegate类实现协议UIApplicationDelegate,它是委托类。
我们给出委托的定义,委托是为了降低一个对象的复杂度和耦合度,使其能够更具通用性将其中一些处理置于委托对象中的编码方式。通用类因为通用性即与 具体应用的无关性而变为框架类,框架类保持委托对象的引用,并在特定时刻向委托对象发送消息。消息可能只是通知委托对象做一些事情,也可能是对委托对象进 行控制。实现原理我们通过一个案例介绍委托设计模式实现原理和应用场景,重新绘制委托设计模式类图。
在古希腊有一个哲学家,他毕生只做三件事情:&睡觉&、&吃饭&和&工作&。为更好的生活,工作效率更高,他会找一个徒弟,把这些事情委托给徒弟做。然而要成为他的徒弟,需要实现一个协议,协议要求能够处理&睡觉&、&吃饭&和&工作&问题。 三者之间的关系。
哲学家类图中, 通用类(Philosopher)保持指向委托对象(ViewController)的&弱引用& (id&PhilosopherDelegate& delegate),委托对象(ViewController)就是哲学家的&徒弟&,他实现了协议 PhilosopherDelegate,PhilosopherDelegate规定了3个方法:-(void) sleep、-(void) eat和-(void) work方法。下面我们看看实现代码,委托协议PhilosopherDelegate.h代码如下:@protocol PhilosopherDelegate@required-(void)-(void)-(void)@end委托协议PhilosopherDelegate定义了3个方法,协议没有m文件,它的定义可以放在别的h文件中。它的实现类就是委托类ViewController的代码如下:////& ViewController.h//@interface ViewController : UIViewController&PhilosopherDelegate&@end////& ViewController.m//@implementation ViewController- (void)viewDidLoad{&&& [super viewDidLoad];&&& Philosopher *obj = [[Philosopher alloc ] init];&&& obj.delegate =&&& [obj start];}#pragma & PhilosopherDelegate 方法实现-(void) sleep{&&& NSLog(@&sleep&&);}-(void) eat{&&&& NSLog(@&eat&&);}-(void) work{&&&& NSLog(@&work&&);}@end委托对象如何与通用类建立引用关系呢?我们通过viewDidLoad方法中的obj.delegate = self语句来指定委托对象和通用类间的引用关系。 一般情况下通用类由框架直接提供,在这个例子中我们根据需要自己实现了通用类Philosopher,Philosopher.h的代码:////& Philosopher.h//& DelegatePattern//#import &PhilosopherDelegate.h&@interface Philosopher : NSObject{&&& NSTimer *&&&}@property& (nonatomic, weak) id&PhilosopherDelegate&-(void)-(void)@endPhilosopher.h中定义delegate属性,它的类型是id&PhilosopherDelegate&,它可以保存委托对象的引用,属性weak说明是&弱引用&。Philosopher.m文件代码如下://// Philosopher.m//& DelegatePattern#import &Philosopher.h&@implementation Philosopher@-(void) start{&&& count= 0;&&& timer = [NSTimer scheduledTimerWithTimeInterval:3.0&& &&&&&&&&&&&&target:self selector:@selector(handle)userInfo:nil repeats:YES];}-(void)handle{&&& switch (count)&&& {&&&&&&& case 0:&&&&&&&&&&& [self.delegate sleep];&&&&&&&&&&& count++;&&&&&&&&&&&&&&&&&& case 1:&&&&&&&&&&& [self.delegate eat];&&&&&&&&&&& count++;&&&&&&&&&&&&&&&&&& case 2:&&&&&&&&&&& [self.delegate work];&&&&&&&&&&& [timer& invalidate];&&&&&&&&&&&&&& }}@end在本例中Philosopher模拟一些通用类发出调用,这个调用的发出是通过NSTimer每3秒发出一个,依次向委托对象发出消息sleep、 eat和work。代码中self.delegate是指向委托对象ViewController的引用,[self.delegate sleep]是调用ViewController中的sleep方法。
站长在关注}

我要回帖

更多关于 ios cell点击事件 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信