IOS 开发学习

kuailehapp 贡献于2012-12-23

作者 Administrator  创建于2012-08-08 06:28:00   修改者Administrator  修改于2012-08-08 06:38:00字数84477

文档摘要:IOS开发学习IOS开发学习一:Cocoa环境熟悉和Xcode使用。ios开发的前期准备就是一台mac机子。我这边完全是一步一步来的。可能可以跳过很多一。Mac的基础1.首先就是查看你当前的操作系统,能更新升级就升级。2.系统的很多设置,都是在偏好设置选项卡里。主要是输入法。可以下个搜狗。点击 系统偏好设置-》语言于文本-》输入源选择上美国英语和搜狗(和win下操作很像,但是最近发现我的搜狗输入法不太管用了,切换后还是英文的。)3.文件磁盘操作相信在win下习惯了c,d,e,f盘的我们脑子中总会有这样一个概念。
关键词:

IOS开发学习 IOS开发学习一 :Cocoa环境熟悉和Xcode使用 分类: 移动开发_IOS学习 2012-04-21 16:18 851人阅读 评论(0) 收藏 举报 ios开发的前期准备就是一台mac机子。 我这边完全是一步一步来的。可能可以跳过很多 一。Mac的基础 1.首先就是查看你当前的操作系统,能更新升级就升级。 2.系统的很多设置,都是在偏好设置选项卡里。主要是输入法。可以下个搜狗。 点击  系统偏好设置-》语言于文本-》输入源选择上美国英语和搜狗(和win下操作很像,但是最近发现我的搜狗输入法不太管用了,切换后还是英文的。) 3.文件磁盘操作 相信在win下习惯了c,d,e,f盘的我们脑子中总会有这样一个概念。mac下磁盘查看就在finder下。进入后看到左边有一溜,是快捷图表吧(我这么理解)。 那我们要查看自己的个人文档(unix系统习惯基本和linux类似,因为以前整过ubuntu,分区模式基本一样),根目录什么的,finder 中 command+shit+g或者最上面的菜单栏有个前往。然后你可以把需要的几个目录拖到finder的左边(所以我称他为快捷栏)。 4.文件的安装 基本安装的文件都会在应用程序这个目录里,有些程序安装后会有个让你移动到应用程序目录的操作。 5.文件的重名名 这个也是常用操作,mac下不是右键点击有选项,而是直接选中后回车就可以输入新文件名。 暂时这些,基础的。 二。开发环境的搭建 xcode和iossdk。 首先这边我们不能带着Android开发的思路去搞这个。记得我刚搭环境时,一直是:下个sdk,下个xcode  IDE,然后ib插件什么的。 后来发现直接下个xcode就全有了。 xcode下载有很多方法,我是直接在开发者中心:https://developer.apple.com/xcode/ 第一个是for free。然后选右边的 View in mac app store 哦,对了,这边你还必须申请个 apple id。 反正最后在app store里面下来。(优点是简单方便,缺点是速度很慢。) 上面完了后我一直在找怎么下sdk!!! 后来发现其实下完这个xcode 4.3.2后,里面都已经集成了 sdk ,ib,等等一堆。 也就是说,其实我们的环境就这样搭建完成  ios-sdk5.1+xcode 4.x。 不用再去纠结怎么下sdk啊什么的。本人就是Android开发思想,一致在找单独的sdk然后想怎么引入。。 总体以上后,我们简单的环境已经完成,可以使用xcode开发了 三:Xcode4.3.2的介绍和使用 这边又要考虑到ios5的的一些改进和新特新,在使用时很多和网上的资料根本对不上号。 1.比如你在新建一个ios项目时 new-》project 后进入ios的application模板。以前版本据说有个base window。现在没了。 但是也不影响我们创建。对于里面这么多创建对象到底要选哪个呢,记住,永远不要在带着android的模式了,创建一个项目就一个方式, 而这里面的只是快速创建模板。 2.storyboards的引入,这个也是以前版本没有,ios5新加的: StoryBoard    iOS 5的新特新。 http://blog.sina.com.cn/s/blog_59c8adb90100x4oh.html 具体你看下苹果开发者社区或是上面个博客写的,明白大致情况就好了。 3.ARC新特性 Automatic Reference Counting 这个也是ios5新添加的内容,据说和java内存自动释放挺类似的功能。 4.工程的代码作者和公司注释 // //  AppDelegate.h //  Thi // //  Created by Nono on 12-4-13. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved. // 这个和java我们每个类最前面的注释一样。 这个可以在配置文件设置(具体可以网上查下) 我这边用的最简单的一个方法: 在你的系统dock下是否有个“地址簿”的应用或是在finder的应用程序中找下。 点击你当前用户哪个选项编辑下,添加上公司名就ok了。 这下你新建文件时,注释就时你的用户名,和你设置的公司名。 5.interface builder的纠结,一开始我们可能会一直纠结,我的ib插件呢,它到底在哪里呢? 其实不用纠结,它已经集成进xcode了,你点击xib文件后弹出的编辑工具就是ib工具。 6.xcode工具的界面简单介绍: 一开始接触这工具时绝对又是中纠结。但是,我们把它按块划分后,其实就很明了了。这也是做很多事的一种手法。 气泡1:这个栏也不知道给他命名什么,总的来说就是就类似快捷工具栏。左边时run应用启动,选者模拟器,中间一些提示信息, 右边是编辑选择,view也就是界面布局选择,最后一个organizer 按钮  app发布时用得到。 气泡2:工程explorer。 气泡3:编辑区域。 气泡4:感觉类似于属性区域。 基本大体就是这样,然后具体的细分我们可以自己去一个个看。 7.创建一个ios项目后项目结构。 这个可以看上图的气泡2。 Thi就是我创建填写的项目名,这里面就是各种类文件。 Thitest,选择了单元测试后会自动生成这个文件夹。 frameworks: 项目用到的类库。自动生成里面只有基本的几个库,你可以根据项目需要 添加所需要的framework products 貌似就是在发布应用时用到。具体还没测试干嘛的。 以上我们基本就了解怎么在xcode中创建一个ios app,在模拟器中运行。 IOS学习之二:Objective-C基础语法和关键字 分类: 移动开发_IOS学习 2012-04-21 16:33 745人阅读 评论(2) 收藏 举报 对于一门语言得学习,个人觉得最主要得就是其语法格式和那些关键字。 因为对于基本现在大多数得语言,每种语言都是一种符合人思维得方式来与计算机交流。 因此,其实每种语言中定义或是封装好得基础类和类库,其实都是很相似得。 比如 int,double几种基本类型,String,数组,集合以及字典数据类型。 因此你在编程时比如你想以字符串形式和计算机交流,那你很容易就能想到在C中可以使用String这个类,在java中也是Stirng (当然,前提是你至少有一种同抽象级别得语言基础),那OC呢,也有这样一个类吧,不过是某种原因加了个前缀。 那么对于类中定义函数得使用,可能不同语言就有所不同了,首先是函数名(这个其实基本不担心,现在得ide工具提示太强悍了,真不行你可以文档), 其次就是函数得调用格式,我这简单理解为语法格式得一种。 一:以一个最简单得例子来看OC的语法格式。 1.首先一个类得组成,这个知道C的基本没什么说的 .h和.m文件。一个是头文件,一个是实体文件。 OC中一般说是申明文件和实现文件 简单来说,h文件就是整体对一个类得描述,m文件是对h文件中申明描述得实现 [cpp] view plaincopyprint? 1. //    2. //  NonoAppDelegate.h    3. //  MultiViews    4. //    5. //  Created by Nono on 12-4-19.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import     10.    11. @interface NonoAppDelegate : UIResponder    12. {   13.     UITabBarController *tabBarController;   14.     UIWindow *window;   15.    16. }   17.    18. @property (retain, nonatomic)IBOutlet UIWindow *window;   19. @property (retain, nonatomic)IBOutlet UITabBarController *tabBarController;   20. @end   // // NonoAppDelegate.h // MultiViews // // Created by Nono on 12-4-19. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import @interface NonoAppDelegate : UIResponder { UITabBarController *tabBarController; UIWindow *window; } @property (retain, nonatomic)IBOutlet UIWindow *window; @property (retain, nonatomic)IBOutlet UITabBarController *tabBarController; @end 2.先看头文件得格式和申明 #import这个关键字没啥说的,java中叫导入。就是引入你当前类所要用到得依赖库和类。 @interface 申明开头关键字。 后面紧跟的是定义额类名  :后面的是继承得类 UIResponder ,< xxxxxxxxx>有点类似于java中得接口,当然 OC中有个 更加准确得定义就叫协议 ,<>放协议类。 整个申明最后都以@end结束。 { }里面就是常说得申明成员变量。 @property 属性,我暂时理解为也有点成员变量的意思。 这个属性更多是和后面得m文件中的的synthesize关键字有密切联系。 (retain ,nonatomic)属性的一些参数。这个具体可以去看文档,估计C语言额同学应该不陌生,我不是很明确每个参数比较适合得场合。 IBOutlet 关键字,这个是和nib文件息息相关得,只要在nib文件中需要关联的对象,用这个修饰(比如我nib文件中有个window控件,要和代码中这个对象联系起来 ,那么就用这个关键字申明),申明完后会看到这段代码最左端有个空心圆圈,当你和nib文件中控件关联后,就实心圆圈了。 [cpp] view plaincopyprint? 1. //    2. //  NonoAppDelegate.m    3. //  MultiViews    4. //    5. //  Created by Nono on 12-4-19.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import "NonoAppDelegate.h"    10.    11. @implementation NonoAppDelegate   12.    13. @synthesize window;   14. @synthesize tabBarController;   15.    16. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions   17. {   18.   //  self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];    19.     // Override point for customization after application launch.    20.    // self.window.backgroundColor = [UIColor whiteColor];    21.     self.window.rootViewController = self.tabBarController;   22.     [self.window makeKeyAndVisible];   23.     return YES;   24. }   25. @end   // // NonoAppDelegate.m // MultiViews // // Created by Nono on 12-4-19. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "NonoAppDelegate.h" @implementation NonoAppDelegate @synthesize window; @synthesize tabBarController; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; // Override point for customization after application launch. // self.window.backgroundColor = [UIColor whiteColor]; self.window.rootViewController = self.tabBarController; [self.window makeKeyAndVisible]; return YES; } @end 3.实现文件。implmentationxxx    @end。这个不用说了吧。 @synthesize 这个关键字有点意思。这个关键字得表示法后,编译器就自动隐式生成一个setter和getter,OC上得说法来说就是自动实现一个 存取方式。然后我们知道,oc语言这个习惯方式,一个方法和属性在使用前都必须有个申明,就是 h和m文件这个构造啦。那对于h头文件中property 我们是不是可以理解,这是对编译器得一个申明,我将在实现文件中实现这个对象得存取方法,而在m实现时只不过我们一个关键字后让编译器去做了这个事。 4.例子最后说下OC中对象得方法得调用 比如在java中我要调用 a对象的functionA()方法,直接用得点表示法  a.functionA(); 在OC中有点奇特表示成 [a  functionA],如果方法呀传参数,那么紧跟着 functionA :obj 二:一些关键字和部分理解点(以下纯粹是个人觉得OC得一些变异点和需要大致理解得一些事项) 1.NS前缀。OC得大部分类都有这个前缀。要理解缘由,可以去看OC得历史。 2.Bool 这个数据类型有点改动,在常见得语言中都是true和false,OC是YES和NO。 3.@protocol关键字,这个是申明协议类时,和@end连用,看字面意识就知道了。 对于协议我们上面提到,有点类似于java中得接口,当众所周知,接口中申明得方法必须全部实现。java中当然对这样一个强自行手段有引申出 抽象abstract这个类来对这种强制手段一个缓和,OC中则直接在协议类中申明了这一点,对于有些方法不需要强制实现,可选得,用了optional。 这个你可以具体随意跳入哟个协议类看就好了,相信在以后更多代码接触后会有个更深得理解。 4.对于刚接触oc语言得人可能有个小疑惑得类型 (id),这个可以理解为java语言中得泛型 OC得基础语法其实不多,我基本看的是绿柚子那本 OC基础教程。说实话,如果你有面向对象基础,那基本半本你就跳过去了,如果你有C基础,那内存那些 篇章你也可以跳过去了。因为书不厚,我基本是花了周末看了下,对于入门来说,还算本不错的书。适合我们新入门的菜鸟。 对于OC的基础教程文章网上也很多,基本就是带你过一遍类的API,比如String啊,集合啊,数组啊等等。 我觉得以后直接在编写ios例子时引入然后介绍即可,本人也懒。有这方面意向的可以直接去网上找,敲一下熟悉下其实也是不错的。      看完绿柚子,OC的基础 暂时就这些。因为我只做了这么点笔记。对于面向对象和内存,类别,这个有时间我在去看下然后再写下分享。 -----------2012.04.18 IOS学习三:Objective-C的扩展OOP,类别,内存管理等 分类: 移动开发_IOS学习 2012-04-22 14:54 408人阅读 评论(0) 收藏 举报 其实自己也不知道这些概念怎么写,总不能直接从书上copy吧,那还不如买书了,这多累。 对于一些抽象的概念,一般都是大师写的。比如那本可以当枕头的java编程思想。那真的是思想啊。1遍过后绝对跟看小说似的,模模糊糊。 而抽象着东西并没有什么很好的定义,因为它无法定义。 真正的理解,可能还是要我们自己的时间和积累。 这会儿我业余学习ios一周,目前红柚子那本刚好边看边实践到选取器有关的那部分。 我虽有做笔记,但我的笔记基本只带几个关键字。 几天的代码例子实践下,因为现在的开发环境时sdk5.1+xcode4.3.2,无论时xcode下的分布的项目文件结构,nib,storyboarder,arc机制,变化还是挺大的。 就结合oc基础罗嗦下。 一:OOP思想,面向对象这个概念性东西大家应该都有。 什么继承,封装,多态这些就跟背单词一样。但是,简单的还是需要用大白话能说出来的。 先说封装:封装我觉得其实是oop思想最原始的一个基础。封装的引入后,才能衍生出对象这一概念。我们把一个物体和它拥有的属性和更能包装起来,是一个抽离然后融合的过程。 继承:继承从字面句很好了解,儿子继承父亲。一个物体派生出一个新的物体。当然,继承后的很多特性,你可以背书去。 多态:多态其实更好解释了,听字面,多种形态?一个事物的多种实现(当然,这个可能很直观很字面,但是从严谨性上来说是错误的)因为一个物体的多种实现,怎么 看怎么听都是像继承啊,比如我有个鱼类,那么我可以派生一个鲨鱼类和一个鲸鱼类,那对于这个做法来说,感觉是继承啊。其实他们的本质思想都是差不多的, 只是侧重点的不同。继承更像表达一个物体派生一个新物体,多态则是一个物体派生出多个物体对改物体的不同实现,这个实现最直接的方式就是对超类中方法的不同的覆写和实现。比如鱼类,有个eat()方法,派生的鲨鱼类,我们都知道鲨鱼吃肉,那么我们可以实现鲨鱼的eat方法是吃肉的,蓝鲸我们算他杂食吧,那么蓝鲸的eat方法则是实现杂食吃法。此时你就可以站在一个全面的角度简单的看到多态这个概念了。 对于深入理解OOP这个思想定义,其实就类似于看你对待事物抽象的高度。 二:新事物的或者说一个新类产生的集中方式。 1.最原始得一种,就是我们自己抽象定义除一个类。比如定义最原始的类,在java和OC中都存在这样一个原始类Object。 2.继承而来派生出一个新类。这个很好理解。比如从人类Human衍生出男人类 Man, 3.还有一种是我们比较少明确意识到,但是其实是很常用到方法:复合,既用几个不同的类来复合成一个新类。最常用就以书上例子解释 ,Car 汽车类, 简单我们可以用Engine引擎和Tires轮子来构造成最简单的Car模型。 三:OC中类别和非正式协议概念 1.category,类别应该算是OC独有的一个术语,书上给类别的定义是:一种为现有类添加新方法的一种方式。 其实这个方式怎么听怎么像创建子类就可以做到的概念。 是的,为一个类做扩展,我们最常想到的方法就是为其创建一个子类,然后添加你需要扩展的新方法等。 但是在OC中有时这样并不方便,书上举例了一个NSString的例子。原话是这样的: /********** 当希望为新有类添加新的行为时,我们通常会创建子类。 但是有时子类并不方便。例如,你可能会希望为NSString类新增一些新行为,但是你知道,NSString实际上只是一个类簇的前台表示,因而无法 为这样的类创建子类。省略1000字。 ********/ 好了,从上面我们基本知道,创建子类这个方法是有局限性的对吧。上面引入一个概念叫类簇。 字面意思(一簇鲜花,就是许多朵花扎成一束呈现出来,里面的具体其实我们是不知道的。) 类簇其实也算是个不大不小的概念。集体可以看官方文档 http://www.apple.com.cn/developer/mac/library/documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/chapter_3_section_9.html 鄙人也是新接触这玩意儿,里面有这么一句话: /***** 类簇将一些私有的、具体的子类组合在一个公共的、抽象的超类下面。 ****/ 我不知道是不是可以理解。类簇包含的成分是带有私有性质的,但我们都知道,继承后的子类是不能访问父类的私有成员的(这个应该没错吧?) 那么我们在新创建的子类添加的新方法就无权限访问那些东西咯。 好吧,以上是个人理解,这东西也是听拗口的,具体详情可以参考更多官方文档。 那么,好了,我们大体上知道OC引入类别这个机制的原因了。配合上OC动态运行时的分配机制,你可以为现有类添加新的方法,嘿,这 听起来很酷!(书上原话) 类别创建: @interface  NSString(NumberConvenience) -(NSNumber *)lengthAsNumber; @end//NumberConvenience 声明有两个特点:      (1)现有的类位于@interface关键字之后,其后是位于圆括号中的类别名称。类别名称是NumberConvenience,而且该类别将向NSString类中添加方法。换句话说:“我们向NSString类中添加一个名称为NumberConvenience的类别。”同名类别有唯一性,但是可以添加任意多的不同名类别。      (2)可以执行希望向其添加类别的类以及类别的名称,还可以列出添加的方法         不可以添加新的实例变量,类别生命中没有实例变量部分。 类别的实现基本和一般类的实现一样。 非正式协议和委托:非正式协议概念其实就是类别的另一种表达方式“这里有一些你可能希望实现的方法,你可以使用他们更好的完成工作”。 这个意思是,这些是可选的。比如我门要一个更好的方法,我们就会申明一个这样的类别去实现。然后你在后期可以直接使用这些更好的方法。 这么看,总觉得类别这玩意儿有点像协议的可选协议。 可选协议只不过是有先见之明,类别是后期补救。共同一点时,对于方法实现都是可选的。可选协议有关键optionnal申明了,类别则你像高效方法你就申明, 不想就算了。 之后是委托,算OC中一个很重量级的概念。据说深入后会发现很多东西,主要鄙人目前还只接触几天,对于它在oc中整体的设计模式理论还是不太了解。 只是在写例子代码时,怎么看怎么觉得就如java中的监听和回调。可能要更好的理解,那还是要更多的接触代码才能会有个深刻的理解。 四:内存管理的改变 只所以说内存管理的改变,是以前一直说c和c++成员的在工作中最需要注意的问题就是内存管理。 在接触ios5.1前,网上看了大部分资料,内存管理都有很重要的戏份。 只是,当我学习时,发现,这块被淡化了。 现在版本的新特性引入了ARC机制。感觉完全变的和java一样了。 在创建项目选者ARC选项后,你会发现在代码中你根本不用手动去释放内存了。release什么都被划掉了 = =。 不知道这算时好事还是坏事。可能对于我们新手来说,哇。。方便了好多。 暂完 -------2012.04.22笔记整理 IOS学习四:基础控件Label,textfield,button等使用 分类: 移动开发_IOS学习 2012-04-25 23:39 1224人阅读 评论(6) 收藏 举报 本来应该早写这个学习笔记的。 但是写blog真是件痛苦得事。 今天刚面试了一个来IOS开发的同学。我觉得我得加紧进度啦。 学习进度:本例子是学习4天后红柚子第一个完整例子代码,基本把oc基础看完后实践的, 其实发现这个例子完完全全是为熟悉IB插件拖来拉去布局而来的。 这边申明两个方面,也是面试3个同学后给的提议,也是论坛上很多给的提议: 1.不建议使用IB文件来布局,界面文件还是需要代码写,后期维护起来简单。并且在拖来拖去时遗漏一个输出口就很悲剧。 而且大牛们都建议纯代码写,这点我也考虑到如何保持界面得美观,因为代码得话我没法实时查看布局效果,这个绝对是ANdroid开发 时一个很大额问题,不过ios上基本没事,因为ios屏幕得统一性,一般情况下美工绘制完界面后会把每个控件得坐标都给你。 当然,喜欢xib文件得也可以,甚至storyboarder。只是说,要有代码熟练书写控件得能力。 2.ARC机制,问了下最近部分培训出来的,基本是iso5.0+xcode4.2,其实这些新特性都引入了。 本来应该是个好事,但是,有个同学说,他们老师暂时不建议直接用ARC机制,首先,这样会渐渐丧失内存管理的概念(当然u作为一个从java过来的人,谈不上丧失 因为本来就没有),其次是在ios开发中会大量引入第三方库,那些库在没有支持ARC机制下,那么整个项目可能就会出现问题。因此在开发中要自己考虑周到, 当然,我是希望这个机制最终能被我开发者完全接受,毕竟省力是一件讨好的事。 正题: 我们先用xcode建立一个最简单得例子 1.打开xcode引导新建一个Project,我这边选这个模板 然后填写一些项目的基本命名和属性 第一个项目名,第二项类似于android中得包名,貌似是app唯一标识。 第四项,类前缀,默认是没有,写上后模板生成得几个类前默认带个这个前缀。 说下最后三个复选框。 第一个就是我们说的新特性之一,用storyboards管理布局文件。 第二个arc机制 第三个自动生成一个测试用例。 这次我全不选,不过我学的时候选了ARC,完全不用释放内存。这回是听了那几个朋友的建议,初学者要给自己较好的编码意识。 2.创建完后我们来大致看下目录结构分析,然后应用是如何启动的 一般我们在看一个整体应用时,我们都会去了解这个应用到底是怎么起来的(Android比如简单的就是一个入口activity。当然在往前点可能说是Applicaton) ios中,则是在用户点击应用后,会进入这个main函数。然后我们看了下这个函数唯一能让我们关联得就是NonoAppDelegate这个类 (我这边比较俗,既看一个应用启动流程时,我保证代码能把我整个应用窜起来,不考虑后台到底怎么怎么进程,loop啊,队列什么的,目前对我们来说太深奥了)。 好了,这个main之后能跳到我们的代理类了。 我们看下代理类中内容 [cpp] view plaincopyprint? 1. //    2. //  NonoAppDelegate.h    3. //  TestOne    4. //  Created by Nono on 12-4-25.    5. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    6. //    7.    8. #import     9.    10. @class NonoViewController;   11.    12. @interface NonoAppDelegate : UIResponder    13.    14. @property (strong, nonatomic) UIWindow *window;   15. @property (strong, nonatomic) NonoViewController *viewController;   16. @end   // // NonoAppDelegate.h // TestOne // Created by Nono on 12-4-25. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import @class NonoViewController; @interface NonoAppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @property (strong, nonatomic) NonoViewController *viewController; @end 以上这是头文件。 [cpp] view plaincopyprint? 1. @synthesize window = _window;   2. @synthesize viewController = _viewController;   3.    4. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions   5. {   6.     self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];   7.     // Override point for customization after application launch.    8.     self.viewController = [[[NonoViewController alloc] initWithNibName:@"NonoViewController" bundle:nil] autorelease];   9.     self.window.rootViewController = self.viewController;   10.     [self.window makeKeyAndVisible];   11.     return YES;   12. }   @synthesize window = _window; @synthesize viewController = _viewController; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; // Override point for customization after application launch. self.viewController = [[[NonoViewController alloc] initWithNibName:@"NonoViewController" bundle:nil] autorelease]; self.window.rootViewController = self.viewController; [self.window makeKeyAndVisible]; return YES; } 实现文件我们就看部分。 该实现方法是应用启动完后,加载一个窗口,然后在窗口上添加各种View。 这边说个小注意点。 在main函数时,我们会看到两种书写: 第一种: [cpp] view plaincopyprint? 1. int main(int argc, char *argv[])   2. {   3.     @autoreleasepool {   4.         return UIApplicationMain(argc, argv, nil, nil);   5.     }   6. }   int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, nil); } } 第二种: [cpp] view plaincopyprint? 1. int main(int argc, char *argv[])   2. {   3.     @autoreleasepool {   4.         return UIApplicationMain(argc, argv, nil, NSStringFromClass([NonoAppDelegate class]));   5.     }   6. }   int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([NonoAppDelegate class])); } } 我们可以看到UIApplicationMain方法参数不一样。 对于这个,这哥们得博文写的比较明了了:《Main方法得讨论》 http://blog.csdn.net/nicktang/article/details/6796932 3. 以上基本一个带窗口单空白视图的得应用就起来了。现在,我们集合IB控件往该视图上添加一些常用的基础控件 首先我们在NonoViewController.h定义一些属性控件申明输出口,以及按钮IBAction连接入口 [cpp] view plaincopyprint? 1. #import     2.    3. #define kSwitchIndex 0    4. @interface NonoViewController : UIViewController   5. {   6.     UITextField *userNameText ;   7.     UITextField *passWordText ;   8.     UILabel *sliderLabel;   9.     UISlider *slider;   10.     UISwitch *switchButton;   11.     UIButton *button;   12. }   13.    14. @property (nonatomic , retain) IBOutlet UITextField *userNameText;   15. @property (nonatomic , retain) IBOutlet UITextField *passWordText;   16. @property (nonatomic , retain) IBOutlet UILabel *sliderLabel;   17. @property (nonatomic , retain) IBOutlet UISwitch *switchButton;   18. @property (nonatomic , retain) IBOutlet UIButton *button;   19.    20. -(IBAction)textFieldDoneExting:(id)sender;   21. -(IBAction)backgroundTap:(id)sender;   22. -(IBAction)sliderChanged:(id)sender;   23. -(IBAction)segementButton:(id)sender;   24. -(IBAction)switchchanged:(id)sender;   25. -(IBAction)buttonOnclick:(id)sender;   26. @end   #import #define kSwitchIndex 0 @interface NonoViewController : UIViewController { UITextField *userNameText ; UITextField *passWordText ; UILabel *sliderLabel; UISlider *slider; UISwitch *switchButton; UIButton *button; } @property (nonatomic , retain) IBOutlet UITextField *userNameText; @property (nonatomic , retain) IBOutlet UITextField *passWordText; @property (nonatomic , retain) IBOutlet UILabel *sliderLabel; @property (nonatomic , retain) IBOutlet UISwitch *switchButton; @property (nonatomic , retain) IBOutlet UIButton *button; -(IBAction)textFieldDoneExting:(id)sender; -(IBAction)backgroundTap:(id)sender; -(IBAction)sliderChanged:(id)sender; -(IBAction)segementButton:(id)sender; -(IBAction)switchchanged:(id)sender; -(IBAction)buttonOnclick:(id)sender; @end 然后我们来看对应 xib文件 然后我们来看怎拖拉来与代码中的输出口连接起来。 这边我们先看下xib文件得一些显示: 首先是这个filesOwner,文件拥有者,其实就是下面这些控件对象的拥有者,而我们知道, 拥有这些对象的就是我们的NonoViewController 接下来我们看链接操作: (擦,截这个图我得xcode死掉了好几次 = =。) 很很简单,我们知道filesowner其实就是我们得NonoViewController类,里面有我们申明得几个输出口,要很xib文件建立链接 其实就是我们在该类中定义一个对象,我们需要指向一个实例,该实例就是xib文件中我们拖进去得控件。 好,现在我们点击filesower,然后按住control键,移动鼠标箭头就会出现一个蓝色的线,随便链接到下面的一个控件松开鼠标, 会自动提示你,NonoViewController中得哪几个指针(输出口)可以指向这个控件。这样就把代码和xib文件的对象一一联系起来了。 我们可以看最右边的属性图,可以看出有个Outlets标签,里面刊例浏览当前控件的链接情况。 同时还有个reference outlets,其实刚和和上面相反,这个看字面意思就是引用得输出口 此刻我们以一个输入用户名得textField举例,我们知道filesOwner中(也就是NonoViewController)有用户名的输出口,指向了xib中的输入用户名。 那么对应得 我们选中userNameText这个控件后,他的reference outlet是在filesowner中 当你把这个关系理清楚后,那么布局与代码的链接就很简单了。 同样得,我们能看到如果是按钮类型的,会有个event动作得输出口,设计理念基本上理解上面这种后,这个是很容易明白的。 然后对于每个textfield,button什么的细节设置,都可以在右边得属性栏中修改。 5.以后我们基本就申明完一个控制类了,然后是实现类了。 不好意思,本来说重写下不用ARC机制的,当这会都11点了,没心情重写下,copy早几天写的那个讲究看下了 [cpp] view plaincopyprint? 1. //    2. //  NonoViewController.m    3. //  ApressFirst    4. //    5. //  Created by Nono on 12-4-17.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import "NonoViewController.h"    10.    11. @implementation NonoViewController   12. @synthesize userNameText;   13. @synthesize passWordText;//该定义会自动实现setter和getter方法    14. @synthesize sliderLabel;   15. @synthesize switchButton;   16. @synthesize button;   17. //定义得按钮事件1    18. -(IBAction)switchchanged:(id)sender   19. {   20.     UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"U will die!" delegate:self cancelButtonTitle:@"OK" destructiveButtonTitle:@"i know"     21.         otherButtonTitles: nil];   22.     [sheet showInView:self.view];   23.    24. }   25. //定义的按钮事件2    26. -(IBAction)buttonOnclick:(id)sender   27. {   28.     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"警告提示!" message:@"你点击了按钮!" delegate:self cancelButtonTitle:@"确定"   29.         otherButtonTitles:@"测试下", nil];   30.     [alert show];   31. }   32.    33. -(IBAction)segementButton:(id)sender   34. {      35.     if([sender selectedSegmentIndex] == kSwitchIndex)   36.     {   37.         switchButton.hidden = NO;   38.         button.hidden = YES;   39.        40.     }else {   41.         switchButton.hidden = YES;   42.         button.hidden = NO;   43.     }   44.    45. }   46.    47. -(IBAction)sliderChanged:(id)sender   48. {   49.     UISlider *uiSlider = (UISlider*)sender;   50.     int size = (int)uiSlider.value;   51.     NSString *sizeText = [[NSString alloc] initWithFormat:@"%d",size];   52.     sliderLabel.text = sizeText;   53.    // [sizeText release];    54. }   55.    56. -(IBAction)textFieldDoneExting:(id)sender   57. {   58.     [sender resignFirstResponder];//放弃当前焦点    59.     //隐藏键盘    60. }   61.    62. -(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex   63. {   64.     NSLog(@"我靠!!!");   65. }   66. -(IBAction)backgroundTap:(id)sender   67. {   68.     [userNameText resignFirstResponder];   69.     [passWordText resignFirstResponder];   70.     //点击背景后隐藏键盘    71. }   72.    73. - (void)viewDidLoad   74. {   75.     [super viewDidLoad];   76. //    NSString *sizeValues = [[NSString alloc] initWithFormat:@"%d",slider.t]    77. //    sliderLabel.text =     78.         // Do any additional setup after loading the view, typically from a nib.    79. }   80.    81. //- (void)dealloc    82. //{    83. ////    [userNameText release];//如果引入得arc机制后该方法无需调用。    84. ////    [passWordText release];    85. //    [super dealloc];    86. //}    87. - (void)viewDidUnload   88. {   89.     [super viewDidUnload];   90.     // Release any retained subviews of the main view.    91. }   92.    93. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation   94. {   95.     return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);   96. }   97.    98. @end   // // NonoViewController.m // ApressFirst // // Created by Nono on 12-4-17. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "NonoViewController.h" @implementation NonoViewController @synthesize userNameText; @synthesize passWordText;//该定义会自动实现setter和getter方法 @synthesize sliderLabel; @synthesize switchButton; @synthesize button; //定义得按钮事件1 -(IBAction)switchchanged:(id)sender { UIActionSheet *sheet = [[UIActionSheet alloc] initWithTitle:@"U will die!" delegate:self cancelButtonTitle:@"OK" destructiveButtonTitle:@"i know" otherButtonTitles: nil]; [sheet showInView:self.view]; } //定义的按钮事件2 -(IBAction)buttonOnclick:(id)sender { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"警告提示!" message:@"你点击了按钮!" delegate:self cancelButtonTitle:@"确定" otherButtonTitles:@"测试下", nil]; [alert show]; } -(IBAction)segementButton:(id)sender { if([sender selectedSegmentIndex] == kSwitchIndex) { switchButton.hidden = NO; button.hidden = YES; }else { switchButton.hidden = YES; button.hidden = NO; } } -(IBAction)sliderChanged:(id)sender { UISlider *uiSlider = (UISlider*)sender; int size = (int)uiSlider.value; NSString *sizeText = [[NSString alloc] initWithFormat:@"%d",size]; sliderLabel.text = sizeText; // [sizeText release]; } -(IBAction)textFieldDoneExting:(id)sender { [sender resignFirstResponder];//放弃当前焦点 //隐藏键盘 } -(void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex { NSLog(@"我靠!!!"); } -(IBAction)backgroundTap:(id)sender { [userNameText resignFirstResponder]; [passWordText resignFirstResponder]; //点击背景后隐藏键盘 } - (void)viewDidLoad { [super viewDidLoad]; // NSString *sizeValues = [[NSString alloc] initWithFormat:@"%d",slider.t] // sliderLabel.text = // Do any additional setup after loading the view, typically from a nib. } //- (void)dealloc //{ //// [userNameText release];//如果引入得arc机制后该方法无需调用。 //// [passWordText release]; // [super dealloc]; //} - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); } @end 以上实现基本没什么太多内容。 方法中会有调用几个对话框控件 UIAlertView基本就是这么一个样子: 一般来说alert就是一个警告对话框,只要一个确认按键点击后对话框消失就好了,但是又时我们又会希望点击确认或是如上面我自己添加得测试下这个按钮 我们希望又相应得处理,那么就可以引入UIActionSheetDelegatede 委托, 同样样还用到一个UIActionSheet 同样是拥有相应得委托协议。 这些其实都是很具有通行的,一开始可能比较乱,看过2-3个后就觉得,原来如此。 然后我们看下这个方法: -(IBAction)textFieldDoneExting:(id)sender {     [sender resignFirstResponder];//放弃当前焦点     //隐藏键盘 } ios中得输入不同于Android,他得显示和显示一般要手动去去做,这个方法我们是链接了我们定义的控件event方法。 上面这个方法在点击done时出发,类似与告诉程序,输入完了,取消键盘。 但是当我们对输入格式什么得做了默写限制时,比如,该输入框只能输入数字。 那貌似没有这个done操作了。 还好,一般ios默认或是长期得用户习惯取消键盘显示得操作就是点击键盘区域外得任意点取消键盘显示。 那么外面的区域其实是对应得xib中得view这个对象,此时我们需要将他强转化成UIController类型,因为只有此类型才会在属性中显示event链接选项。 然后我们给他设置一个touchdown事件出发相应得方法: -(IBAction)backgroundTap:(id)sender {     [userNameText resignFirstResponder];     [passWordText resignFirstResponder];     //点击背景后隐藏键盘 } 好了。睡觉。以上主要是怎么用ib来实现布局。很基础也很简单到此 (昨儿停电断网了,csdn博客怎么没有实时保存功能么,今天一看发现就前半部分了。晕哦) IOS学习五:UITabBarController初步 分类: 移动开发_IOS学习 2012-05-02 09:12 831人阅读 评论(0) 收藏 举报 UiTabBarController这个控制器绝对是项目架构时做常用的一个控件。 我们大致看下控件的效果,我们就知道为什么说他常见了。 这就是最简单的一个雏形,想必现在基本70%的应用界面结构都会是这样的。 在Android中我们以ActivityGroup或是现在的fragment来实现,一个容器中包含多个子控制器。 下面我们还是以建立xib文件的形式来实现一个这样的整体布局的例子。 当然在 xcode4.3.2中我们会发现其实直接有这么一个模板了 但是直接使用模板后会发现是直接在代码里实现了子布局得添加,由于我们不熟练,对于item,tabbar什么的图片文字自定义,一下子找不到代码里的api, 可能说用xib来实现可以看得比较明了。 据说以前直接有base_window模板,不过没关系,模板只是为了给我快速建立一个应用而已,我们这边手动的从最基础得开始 1.首先建立一个Empty Application 2.建立完后我们自定顶一个MainWindow.xib(当然,这个名字可以随意取,但是按照规范以及一种默认留下来的习惯),作为应用启动时加载的首个nib文件, 在新建xib文件你可以选择window也可以是empt什么,其实都差不多,我们这边选window模板得xib文件 3.然后我们其实是要把XXXAppdelegate和这个xib文件连接起来。因此把.h文件定义成这样: [cpp] view plaincopyprint? 1. #import     2.    3. @interface NonoAppDelegate : UIResponder    4. {   5.     UIWindow *window;   6.     UITabBarController *tabTarController;   7. }   8.    9. @property (retain, nonatomic) IBOutlet UIWindow *window;//该控件模板生成是不带IBOutlet的,但是我们为了xib文件布局得统一性,将其也作为一个输出口和在Mainxib中连接起来可以    10. @property (retain, nonatomic) IBOutlet UITabBarController *tabTarController;   11. @end   #import @interface NonoAppDelegate : UIResponder { UIWindow *window; UITabBarController *tabTarController; } @property (retain, nonatomic) IBOutlet UIWindow *window;//该控件模板生成是不带IBOutlet的,但是我们为了xib文件布局得统一性,将其也作为一个输出口和在Mainxib中连接起来可以 @property (retain, nonatomic) IBOutlet UITabBarController *tabTarController; @end 4.然后我们来大致设计我们的xib文件,打开MainWindow.xib文件,我们大致看到视图元素,一个是文件拥有者Filesowner,然后是reponder(这个一直没 怎么用到,具体干吗使的还不是明确),然后最主要得是Object这个标签下得元素,此时就一个window。 首先我们要将文件拥有者这个类改成UIApplication,点击File'sOwner标签后在右侧的属性栏选择Indentity  inspector,看到此时customclass是NSobject, 我们改成UIApplication,改完后会发现File'sOwner得Outlets用了一个delegate的输出口东东,看过上一篇关于outlets和reference outlet我们就知道, 这个东东等会可以指向一个实例对象什么的。 5.好了,那么我们在object下的添加一个delegate的对象,操作很简单,在右侧控件组中 拖一个这样得对象到xib下得Object标签下, 然后我们来自定这个对象,根据上面所知,我们大致可以知道我们需要一个类似于delegate类得对象,对了 我们的AppDelegate不就刚好是这么一个东西么。于是很自然的,选中这个object然后在右侧属性栏将custom class设置成NonoAppDelagate。 然后点击File's Owner将其输出口delegate和我们刚放上去的NonoAppdelagate链接起来。 6.设置完以上后,我们可以点击Object下得XXXAppDelegate,然后看右边属性栏的 Outlets,对了,我们刚在该文件得.h中申明过两个输出口,此刻我们是 要创建两个这样的对象然后将其连接起来。window这时已经有了,还少个UITabBarController。那么我们从右边拖个过来咯 然后输出口和对象链接起来。 此刻,最基本的tabbarcontroller布局框架就ok了,此刻的xib文件如下图 然后我们打开AppDelegate.m进行实现和修改 [cpp] view plaincopyprint? 1. #import "NonoAppDelegate.h"    2.    3. @implementation NonoAppDelegate   4.    5. @synthesize window ;   6. @synthesize tabTarController ;   7.    8. - (void)dealloc   9. {   10.     [self.window release];   11.     [self.tabTarController release];   12.     [super dealloc];   13. }   14.    15. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions   16. {   17. //    self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];    18.     // Override point for customization after application launch.    19.     self.window.backgroundColor = [UIColor whiteColor];   20.     self.window.rootViewController = self.tabTarController;   21.     [self.window makeKeyAndVisible];   22.     return YES;   23. }   #import "NonoAppDelegate.h" @implementation NonoAppDelegate @synthesize window ; @synthesize tabTarController ; - (void)dealloc { [self.window release]; [self.tabTarController release]; [super dealloc]; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; // Override point for customization after application launch. self.window.backgroundColor = [UIColor whiteColor]; self.window.rootViewController = self.tabTarController; [self.window makeKeyAndVisible]; return YES; } 恩,就是这么简单。 理论上我们现在启动模拟器后程序可以启动了。 但是却发现起来后是空白的。 我们从应用的main.m中看 [cpp] view plaincopyprint? 1. int main(int argc, char *argv[])   2. {   3.     @autoreleasepool {   4.         return UIApplicationMain(argc, argv, nil, NSStringFromClass([NonoAppDelegate class]));   5.     }   6. }   int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([NonoAppDelegate class])); } } 然后应用到了我们自定义得delegate类了,然后发现一个问题,按照这个流程,我们MainWindow.xib文件貌似没加载进来啊. 这就对了,以前我们定义个controller的xib文件后都会有initWithNibName,而对于UIApplication类型的xib文件(其实局势整个应用最先要启动的一个类), 据说是这样得加载 这个具体你可以去看上一篇中提到过ios应用启动内容,有个不错得博文给了很好得一个解释。 此刻我们可以将main.h代码稍微修改下 [cpp] view plaincopyprint? 1. #import     2.    3. #import "NonoAppDelegate.h"    4.    5. int main(int argc, char *argv[])   6. {   7.     @autoreleasepool {   8.         return UIApplicationMain(argc, argv, nil, nil);   9.    10.     }   11. }   #import #import "NonoAppDelegate.h" int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, nil); } } 原本第四个参数是指定AppDelegate,但是我们知道,在加载MainWindow.xib实例化里面一个delegate对象时,我们已经链接了AppDelegate类了, 感觉如果第四个参数指定后,这个类像是被实例化了2次,更多具体内容还是参考上面提到那个博客去看吧。 7.好了。最基本得tabbar界面完成,接下来是往里面添加子控制器。 首先我们来熟悉下UITabBarController这个控件: 从界面我们可以推测出,该控件里面大致上有什么东西: 1>.应该有个类似于管理一组子控件的东西吧。 2>界面下面切换得切换条吧 tabBar 3>当然还回发现有个delegate这样得东西,就是代理对象么。 当然上面是在代码中,我们得到这些属性,做相应得操作。 在xib文件里可能说看上去会比较直观 1>Tab bar里面放的是由一个或是多个TabbarItem组成的数组,每个itm对应一个ViewController。 2>下面得 First,Second等等就是每个Item对应 的Controller,这里也要注意一点,默认的我们我们拖进去一个 TabBarItem,一般我们会设置对应得XXXcontroller.xib文件 之后还需将Custom class改成对应XXXXController类,因为默认的类是UIViewController。这会在应用启动后报错的。 3>tabbarItem中可以设置title ,系统默认的几种图标,还有是自定义图标,以及badgeValue,就是上面标签上每个红色的值, 这个比Android上先见之明多了呵呵。 4> 当底部的按钮超过5个时,系统会自动增加一个more按钮,点击more后,剩余的按钮会被显示出来。         以上就是整个tanbar最简单得构造,子controller用得是api自带的UIViewController。 而,TabarController+NavBar的组合基本就是现在ios上绝大分的模式。 更多tabbar细节的操作就需要在代码中实现了。 TabBarController视图控件基础就简单到此。 IOS学习六:Date Picker, Picker View选取器控件初步 分类: 移动开发_IOS学习 2012-05-02 15:18 703人阅读 评论(0) 收藏 举报 Date Picker控件和Picker View控件其实也是算比较常用到视图。 以下根据红柚子上得几个例子: 分别从(日期选取器)Date Picker   ——>单部件选取器——>多部件选取器——>依赖组建选取器。 这边我们不是一步步从创建一个项目开始,毕竟有过前面两三次的实践后, 对于如何选择性的创建一个最合适的应用基础模板已经很简单了。 这边为了方便视图切换,我们用了前面用到过的TabBarController视图控制器。 下面是对以上4种分别举个小例子 一:日期选取器 就是很简单一个日期组建,触摸滚轮可以选取时间,点击确认弹出你选中得时间。 (不过不知道什么情况,感觉有貌似我这个显示怎么出了个8小时的时差~~,不知道是模拟器还是哪边要设置,比如Android会有个设置系统时区什么的)。 我们先不管这个,这几界面就很简单。我们就看到一个datePicker控件和一个确认控件么(这个都知道在xib文件右边拖拽进来吧) [cpp] view plaincopyprint? 1. //    2. //  NonoFirstViewController.h    3. //  MultiViews    4. //    5. //  Created by Nono on 12-4-19.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import     10.    11. @interface NonoFirstViewController : UIViewController   12. {   13.     UIDatePicker *datePicker;   14.     15. }   16. @property(nonatomic, retain) IBOutlet UIDatePicker *datePicker;//日期选取器    17. -(IBAction)buttonPressed:(id)sender;//按钮操作    18. @end   // // NonoFirstViewController.h // MultiViews // // Created by Nono on 12-4-19. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import @interface NonoFirstViewController : UIViewController { UIDatePicker *datePicker; } @property(nonatomic, retain) IBOutlet UIDatePicker *datePicker;//日期选取器 -(IBAction)buttonPressed:(id)sender;//按钮操作 @end 头文件我们定义了这一个输出口和一个按钮事件 [cpp] view plaincopyprint? 1. //    2. //  NonoFirstViewController.m    3. //  MultiViews    4. //    5. //  Created by Nono on 12-4-19.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8. #import "NonoFirstViewController.h"    9.    10. @implementation NonoFirstViewController   11. @synthesize datePicker;   12. -(IBAction)buttonPressed:(id)sender   13. {   14.     NSDate * selected = [self.datePicker date];//获取选取时间    15.     NSString *date = [[NSString alloc] initWithFormat:@"你选择了:%@",selected];   16.     UIAlertView * alterView = [[UIAlertView alloc] initWithTitle:@"时间提示" message:date delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil];   17.     [alterView show];   18.        19. }   20.    21. - (void)viewDidLoad   22. {   23.     [super viewDidLoad];   24.     NSDate *now = [[NSDate alloc] init];   25.     [datePicker setDate:now animated:YES];   26.     // Do any additional setup after loading the view from its nib.    27. }   28.    29.    30.    31. @end   // // NonoFirstViewController.m // MultiViews // // Created by Nono on 12-4-19. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "NonoFirstViewController.h" @implementation NonoFirstViewController @synthesize datePicker; -(IBAction)buttonPressed:(id)sender { NSDate * selected = [self.datePicker date];//获取选取时间 NSString *date = [[NSString alloc] initWithFormat:@"你选择了:%@",selected]; UIAlertView * alterView = [[UIAlertView alloc] initWithTitle:@"时间提示" message:date delegate:self cancelButtonTitle:@"确定" otherButtonTitles: nil]; [alterView show]; } - (void)viewDidLoad { [super viewDidLoad]; NSDate *now = [[NSDate alloc] init]; [datePicker setDate:now animated:YES]; // Do any additional setup after loading the view from its nib. } @end 实现文件也很简单,基本没什么说的,因为这个控件我们跳进datePicker的头文件,发现其实他就是一种pickerView的封装实现。 对于我们来说,使用范围就比较局限性。看他的类名我们就知道了。 因此很多时候,我们都会需要自定义Picker View 二:Picker View组件 这个就是一个单部件的picker View。 根据我们的思路或是一些开发经验。 看到这么一个东西,大致可以知道:第一,有个展示界面(也就是我们拖进去的PickerView) 第二,需要有填充这个界面的数据源 第三,需要一个我们对该控件相关操作的控制者。 有过Android开发的朋友也该很容易联想到一个东西,就是Adapter,适配器。 其实ios这个也是差不多。 这边提一点,其实IOS这种适配模式等你接触后,就会恍然大悟的发现,就这么一个模式。 一个视图,实现一个数据源协议,实现一个(控制器代理)。 基本所有类似组建得表现形式和操作都是这三者的结合。(MVC模式啊,代理模式啊什么,这算吧,也挺形象了) 废话不多说,先看下头文件 [cpp] view plaincopyprint? 1. //    2. //  NonoSecondViewController.h    3. //  MultiViews    4. //    5. //  Created by Nono on 12-4-19.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import     10.    11. @interface NonoSecondViewController : UIViewController   12. //协议:选取器得数据源,和委托    13. {   14.     UIPickerView * pickerView;   15.     NSArray *pickerData;   16. }   17. @property(nonatomic,retain) NSArray *pickerData;   18. @property(nonatomic, retain) IBOutlet UIPickerView  *pickerView;   19. -(IBAction)buttonPressed:(id)sender;   20.    21. @end   // // NonoSecondViewController.h // MultiViews // // Created by Nono on 12-4-19. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import @interface NonoSecondViewController : UIViewController //协议:选取器得数据源,和委托 { UIPickerView * pickerView; NSArray *pickerData; } @property(nonatomic,retain) NSArray *pickerData; @property(nonatomic, retain) IBOutlet UIPickerView *pickerView; -(IBAction)buttonPressed:(id)sender; @end 申明了需要实现的两个  就是我们上面提到的。 多了一个属性申明 一个数组。等会用于存放数据源。 [cpp] view plaincopyprint? 1. //    2. //  NonoSecondViewController.m    3. //  MultiViews    4. //    5. //  Created by Nono on 12-4-19.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import "NonoSecondViewController.h"    10.    11. @implementation NonoSecondViewController   12. @synthesize pickerData;   13. @synthesize pickerView;   14.    15. //实现申明方法    16. -(void)buttonPressed:(id)sender   17. {   18.     NSInteger row = [pickerView selectedRowInComponent:(0)];   19.     NSString *selected = [pickerData objectAtIndex:row];   20.     NSString *title = [[NSString alloc] initWithFormat:@"你选择的:%@!",selected];   21.     UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:title delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil];   22.     [alert show];   23.        24. }   25.    26. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil   27. {   28.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];   29.     if (self) {   30.         // Custom initialization    31.     }   32.     return self;   33. }   34.    35. - (void)viewDidLoad   36. {  //初始化数据源数据    37.        [super viewDidLoad];   38.     NSArray *array = [[NSArray alloc] initWithObjects:@"陈凯", @"至尊宝",@"菩提老祖",@"二当家",@"紫霞仙子",@"蜗牛",nil];   39.     self.pickerData = array;   40.        41.    42.       // Do any additional setup after loading the view from its nib.    43. }   44.    45. - (void)viewDidUnload   46. {   47.     [super viewDidUnload];   48.     self.pickerData = nil;   49.     self.pickerView = nil;   50.     // Release any retained subviews of the main view.    51.     // e.g. self.myOutlet = nil;    52. }   53.    54. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation   55. {   56.     return (interfaceOrientation == UIInterfaceOrientationPortrait);   57. }   58.    59. #pragma mark -    60. #pragma mark Picker Data Source Methods    61. - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView   62. {   63.     return (1);   64. }   65. - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component   66. {     67.     return [pickerData count];   68. }   69. #pragma mark Picker Delegate Methods    70. //书上介绍说这里面得委托方法是可选得(delegate中用optional修饰),实际上我们至少要实现一个委托方法    71. - (NSString *)pickerView:(UIPickerView *)pickerView    72.              titleForRow:(NSInteger)row    73.             forComponent:(NSInteger)component   74. {   75.     return [pickerData objectAtIndex:row];   76. }   77.    78. @end   // // NonoSecondViewController.m // MultiViews // // Created by Nono on 12-4-19. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "NonoSecondViewController.h" @implementation NonoSecondViewController @synthesize pickerData; @synthesize pickerView; //实现申明方法 -(void)buttonPressed:(id)sender { NSInteger row = [pickerView selectedRowInComponent:(0)]; NSString *selected = [pickerData objectAtIndex:row]; NSString *title = [[NSString alloc] initWithFormat:@"你选择的:%@!",selected]; UIAlertView *alert = [[UIAlertView alloc] initWithTitle:title message:title delegate:self cancelButtonTitle:@"OK" otherButtonTitles: nil]; [alert show]; } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { //初始化数据源数据 [super viewDidLoad]; NSArray *array = [[NSArray alloc] initWithObjects:@"陈凯", @"至尊宝",@"菩提老祖",@"二当家",@"紫霞仙子",@"蜗牛",nil]; self.pickerData = array; // Do any additional setup after loading the view from its nib. } - (void)viewDidUnload { [super viewDidUnload]; self.pickerData = nil; self.pickerView = nil; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); } #pragma mark - #pragma mark Picker Data Source Methods - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return (1); } - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { return [pickerData count]; } #pragma mark Picker Delegate Methods //书上介绍说这里面得委托方法是可选得(delegate中用optional修饰),实际上我们至少要实现一个委托方法 - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { return [pickerData objectAtIndex:row]; } @end 主要看下#pragma mark下得三个方法(pragma干嘛使,其实也不太明白,目前知道感觉就如一个标记东西,不写其实也没关系,写了我们可以看得比较明白 ,以下使我们实现的协议方法。述说貌似对其有个更好的解释,大家可以google或是看书。) 首先,必须实现的两个数据源协议中的方法。 第一个:- (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView {     return (1);//返回在这个pickerView中得部件个数 } 这是什么意思呢?以我的简单理解说下吧。 我们整个视图是一个PickerView,里面可以有单个货多个部件(什么意思?看上面两个截图, DatePicker中4个部件,至尊宝中就是一个部件) 好吧,应该了解了。这个方法得返回值就是返回你所要显示得部件个数。 这边我们知道,我们就一个部件,也只需显示一个部件。 第二个:- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {       return [pickerData count]; } 返回每个部件中要显示数据的条数。说白了就是返回你要填充这个部件的数据源中数据元素的个数,这边就是数组的大小么。 以上两个是数据源的协议方法实现,下面这个是pickerView委托中方法的实现。 当然,这个委托协议中的我们能看到很多方法,但是是可选的,可以根据我们得需要来实现。 但是上面代码也说了,虽然可选,但是基本都会要实现这个方法。 - (NSString *)pickerView:(UIPickerView *)pickerView               titleForRow:(NSInteger)row              forComponent:(NSInteger)component {     return [pickerData objectAtIndex:row]; } 因为我们知道,数据源协议两个方法只不过是和我们得视图做了一个关联, 如何把数据显示出来,就靠这个方法了。 单个部件的基本就是这么简单。 三:多部件控件以及依赖组件 这两个就一起说算了,因为差不多。         两个滚轮,就是多部件组件形式(当然你可以更多)。 组建的相互依赖,也很简单,既当我我第一个滚轮滚到鸟类时,第二个滚轮中得数据是鸟; 鱼儿的时候是鲤鱼鲨鱼。前者就像一个父节点一样。 下面我来定义头文件 [cpp] view plaincopyprint? 1. //  MultiViews    2. //    3. //  Created by Nono on 12-4-20.    4. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    5. //    6.    7. #import     8.    9. #define mFather   0    10. #define mChilder  1    11.    12. @interface NonoDependentOnViewController : UIViewController   13. {   14.     UIPickerView *dependentPickerView;   15.     NSArray *fatherArray;   16.     NSArray *childeArray;   17.     NSDictionary *dictionary;   18. }   19.    20. @property(retain ,nonatomic) IBOutlet UIPickerView *dependentPickerView;   21. @property(retain,nonatomic) NSArray *fatherArray;   22. @property(retain,nonatomic) NSArray *childerArray;   23. @property(retain, nonatomic) NSDictionary *dictionary;   24.    25. - (IBAction)buttonPressed:(id)sender;   26.    27. @end   // MultiViews // // Created by Nono on 12-4-20. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import #define mFather 0 #define mChilder 1 @interface NonoDependentOnViewController : UIViewController { UIPickerView *dependentPickerView; NSArray *fatherArray; NSArray *childeArray; NSDictionary *dictionary; } @property(retain ,nonatomic) IBOutlet UIPickerView *dependentPickerView; @property(retain,nonatomic) NSArray *fatherArray; @property(retain,nonatomic) NSArray *childerArray; @property(retain, nonatomic) NSDictionary *dictionary; - (IBAction)buttonPressed:(id)sender; @end 几个属性,fatherArray就是用于存放第一个滚轮的数据源数组(比如鱼儿,鸟类),childerArray用于存放第二个滚轮的数据源组 实现文件 [cpp] view plaincopyprint? 1. //    2. //  NonoDependentOnViewController.m    3. //  MultiViews    4. //    5. //  Created by Nono on 12-4-20.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import "NonoDependentOnViewController.h"    10.    11.    12. @implementation NonoDependentOnViewController   13. @synthesize dependentPickerView;   14. @synthesize fatherArray;   15. @synthesize childerArray;   16. @synthesize dictionary;   17. //按钮点击效果    18. - (IBAction)buttonPressed:(id)sender   19. {      20.  。。。。   21. }   22.    23. - (void)viewDidLoad   24. {   25.     [super viewDidLoad];   26.        27.     NSBundle *bundle = [NSBundle mainBundle];//此调用的返回的束对象表示我们的应用程序    28.     NSString *path = [bundle pathForResource:@"Fcsource" ofType:@"plist"];   29.     NSDictionary *dic = [[NSDictionary alloc] initWithContentsOfFile:path];   30.     self.dictionary = dic;   31.        32.     NSArray *rootArray = [self.dictionary allKeys];    33.     NSArray *root = [rootArray sortedArrayUsingSelector:@selector(compare:)];   34.     self.fatherArray = root;   35.        36.     NSString *fatherSec = [self.fatherArray objectAtIndex:0];   37.     NSArray *array = [self.dictionary objectForKey:fatherSec];   38.     self.childerArray = array;   39.        40.     // Do any additional setup after loading the view from its nib.    41. }   42.    43. #pragma mark -    44. //数据源协议方法实现    45. // returns the number of 'columns' to display.    46. - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView   47. {   48.     return 2;   49. }   50.    51. // returns the # of rows in each component..    52. - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component   53. {   54.     if (component == mFather) {   55.         return [self.fatherArray count];   56.     }else {   57.         return [self.childerArray count];   58.     }   59. }   60.    61.    62. //选取器委托方法实现    63. //显示在view上    64. - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component   65. {   66.     if(component == mFather){   67.         return [self.fatherArray objectAtIndex:row];   68.     }else {   69.         return [self.childerArray objectAtIndex:row];   70.     }   71. }   72.    73. //一个选取器选取改变另一个依赖得选择器    74. - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component   75. {   76.     if (component == mFather) {   77.         NSString *string = [self.fatherArray objectAtIndex:row];   78.         NSArray *array = [self.dictionary objectForKey:string];   79.         self.childerArray = array;   80.         [dependentPickerView selectRow:0 inComponent:mChilder animated:YES];   81.         [dependentPickerView reloadComponent:mChilder];   82.     }   83.        84.     NSLog(@"触发依赖");   85. }   86. //改变两个部件宽度    87. - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component   88. {   89.     if(component == mFather)   90.         return (100);   91.     return 200;   92. }   93.    94. @end   // // NonoDependentOnViewController.m // MultiViews // // Created by Nono on 12-4-20. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "NonoDependentOnViewController.h" @implementation NonoDependentOnViewController @synthesize dependentPickerView; @synthesize fatherArray; @synthesize childerArray; @synthesize dictionary; //按钮点击效果 - (IBAction)buttonPressed:(id)sender { 。。。。 } - (void)viewDidLoad { [super viewDidLoad]; NSBundle *bundle = [NSBundle mainBundle];//此调用的返回的束对象表示我们的应用程序 NSString *path = [bundle pathForResource:@"Fcsource" ofType:@"plist"]; NSDictionary *dic = [[NSDictionary alloc] initWithContentsOfFile:path]; self.dictionary = dic; NSArray *rootArray = [self.dictionary allKeys]; NSArray *root = [rootArray sortedArrayUsingSelector:@selector(compare:)]; self.fatherArray = root; NSString *fatherSec = [self.fatherArray objectAtIndex:0]; NSArray *array = [self.dictionary objectForKey:fatherSec]; self.childerArray = array; // Do any additional setup after loading the view from its nib. } #pragma mark - //数据源协议方法实现 // returns the number of 'columns' to display. - (NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView { return 2; } // returns the # of rows in each component.. - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component { if (component == mFather) { return [self.fatherArray count]; }else { return [self.childerArray count]; } } //选取器委托方法实现 //显示在view上 - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component { if(component == mFather){ return [self.fatherArray objectAtIndex:row]; }else { return [self.childerArray objectAtIndex:row]; } } //一个选取器选取改变另一个依赖得选择器 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { if (component == mFather) { NSString *string = [self.fatherArray objectAtIndex:row]; NSArray *array = [self.dictionary objectForKey:string]; self.childerArray = array; [dependentPickerView selectRow:0 inComponent:mChilder animated:YES]; [dependentPickerView reloadComponent:mChilder]; } NSLog(@"触发依赖"); } //改变两个部件宽度 - (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component { if(component == mFather) return (100); return 200; } @end (几个默认的我们这边不提及到得方法我delete掉了) 这边我们涉及下一个小的api知识,就是用plist文件存储数据。这个以后也会是常用的。 基本步骤是:1.新定义一个plist文件 2.打开plist文件自定义一些数据源 大致界面就是:   [cpp] view plaincopyprint? 1. NSBundle *bundle = [NSBundle mainBundle];//此调用的返回的束对象表示我们的应用程序    2. NSString *path = [bundle pathForResource:@"Fcsource" ofType:@"plist"];   3. NSDictionary *dic = [[NSDictionary alloc] initWithContentsOfFile:path];   4. self.dictionary = dic;   NSBundle *bundle = [NSBundle mainBundle];//此调用的返回的束对象表示我们的应用程序 NSString *path = [bundle pathForResource:@"Fcsource" ofType:@"plist"]; NSDictionary *dic = [[NSDictionary alloc] initWithContentsOfFile:path]; self.dictionary = dic; 其实就是读取了这个一个文件,后一NSDictionary的对象保存起来。因为我们以xml形式打开这个plist文件 会发现,这货最外层得标签就是一个 [html] view plaincopyprint? 1.    2.    3.    4.    5.     鱼儿   6.        7.         鲤鱼   8.         鲨鱼   9.        10.     鸟类   11.        12.         大鸟   13.         小鸟   14.        15.    16.    鱼儿 鲤鱼 鲨鱼 鸟类 大鸟 小鸟 allkeys后返回所有key对应得value放入一个数组,书本上又对数组做了下排序操作。 默认我们选取了索引为0的父源,以及对应的子源。 然后继续看数据源协议得两个方法,略微有点变化 第一个不说了,返回部件数为2; 第二个// returns the # of rows in each component.. - (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component {     if (component == mFather) {         return [self.fatherArray count]; //如果是父部件,返回填充父部件数据源个数     }else {         return [self.childerArray count];//子部件。。。。。。     } } 同理的,对于pickerView委托方法中这个方法也很好理解 //显示在view上 - (NSString *)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component {     if(component == mFather){         return [self.fatherArray objectAtIndex:row];     }else {         return [self.childerArray objectAtIndex:row];     } } 最主要是这个委托方法实现,也是依赖组件的核心 [cpp] view plaincopyprint? 1. //一个选取器选取改变另一个依赖得选择器    2. - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component   3. {   4.     if (component == mFather) {   5.         NSString *string = [self.fatherArray objectAtIndex:row];   6.         NSArray *array = [self.dictionary objectForKey:string];   7.         self.childerArray = array;   8.         [dependentPickerView selectRow:0 inComponent:mChilder animated:YES];   9.         [dependentPickerView reloadComponent:mChilder];   10.     }   11.        12.     NSLog(@"触发依赖");   13. }   //一个选取器选取改变另一个依赖得选择器 - (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component { if (component == mFather) { NSString *string = [self.fatherArray objectAtIndex:row]; NSArray *array = [self.dictionary objectForKey:string]; self.childerArray = array; [dependentPickerView selectRow:0 inComponent:mChilder animated:YES]; [dependentPickerView reloadComponent:mChilder]; } NSLog(@"触发依赖"); } 看方法名我们可以知道是部件上某条数据(row)被选中后。可以做出相应得操作。 这边我们知道,我们选中了不同得父源后,需要显示相应的子源。 因此我们可以做一些如上得代码操作。 好了。选取期组件初步基本就这些。 这个列子还是好久前写的,因此大伙看到没有 release呵呵,因为我那会创建还是用得ARC。 说简单点,核心就三点: 一个pickerView,一个数据源协议,一个委托协议。 完 IOS学习七:UINavigationController控件的初步 分类: 移动开发_IOS学习 2012-05-03 14:47 415人阅读 评论(0) 收藏 举报 UINavigationController大致的简介截图至一份朋友给的课件 (这个课件我问问看能不能分享出来,因为是他培训机构的课件,内容不多,但是概括性不错。) 然后我们看下例子要实现的简单看下效果                     (不好意思,这个截图手抖了,有点难看。) 好了,现在说下大致步骤 1.首先还是创建一个工程 然后这边我们不用MainWindow.xib方式来实现布局了。 直接代码实现。 我们都知道在应用启动后要创建一个window啊什么的。然后window的根视图等等。这个一般是AppDelegate中完成 [cpp] view plaincopyprint? 1. //    2. //  NonoAppDelegate.m    3. //  NavTest    4. //    5. //  Created by Nono on 12-4-26.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import "NonoAppDelegate.h"    10. #import "NonoFirstLevelViewController.h"    11. @implementation NonoAppDelegate   12.    13. @synthesize window = _window;   14. @synthesize navController = _navController;   15.    16. - (void)dealloc   17. {   18.     [_window release];   19.     [_navController release];   20.     [super dealloc];   21. }   22.    23. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions   24. {      25.     //应用的第一层是个window    26.     self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];   27.     // Override point for customization after application launch.    28.        29.     //放在window上的根视图    30.     UINavigationController  *nc = [[UINavigationController alloc] init];   31.     self.navController = nc;   32.     [nc release];   33.     NonoFirstLevelViewController *tableVc = [[NonoFirstLevelViewController alloc] initWithNibName:@"NonoFirstLevelViewController" bundle:nil];   34.        35.     //将First作为控制器的顶级视图。    36.     [self.navController initWithRootViewController:tableVc];   37.     [tableVc release];   38.     self.window.rootViewController = self.navController;   39.     self.window.backgroundColor = [UIColor redColor];   40.     [self.window makeKeyAndVisible];    41.     return YES;   42. }   // // NonoAppDelegate.m // NavTest // // Created by Nono on 12-4-26. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "NonoAppDelegate.h" #import "NonoFirstLevelViewController.h" @implementation NonoAppDelegate @synthesize window = _window; @synthesize navController = _navController; - (void)dealloc { [_window release]; [_navController release]; [super dealloc]; } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //应用的第一层是个window self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease]; // Override point for customization after application launch. //放在window上的根视图 UINavigationController *nc = [[UINavigationController alloc] init]; self.navController = nc; [nc release]; NonoFirstLevelViewController *tableVc = [[NonoFirstLevelViewController alloc] initWithNibName:@"NonoFirstLevelViewController" bundle:nil]; //将First作为控制器的顶级视图。 [self.navController initWithRootViewController:tableVc]; [tableVc release]; self.window.rootViewController = self.navController; self.window.backgroundColor = [UIColor redColor]; [self.window makeKeyAndVisible]; return YES; } 视图放置顺序基本就是 window ——NavigationC——FirstLevelVC。 然后我们会看到蓝色的导航条上的标题,以及后面要涉及到的回退,操作按钮。 IOS开发中得操作习惯一开始还是很难适应的。 理论上来说对于蓝色框内(也就是导航条本身的设置),我们应该是获取navc对象本身来进行操作,但是貌似 熟悉了代码后,发现对于导航条上修改和设置是通过当前被展示得视图的视图控制去设置。 下面我们看下FirstLevel,也就是导航控制器中顶级视图实现类的部分代码 [cpp] view plaincopyprint? 1. - (void)viewDidLoad   2. {   3.     [super viewDidLoad];   4.     self.title = @"第一级视图";   5.    // self.navigationItem.title = @"第一级视图";//设置导航控制标题    6.        7.     //实现一个右边按钮,默认顶级视图是没有左右按钮的    8.     UIBarButtonItem *rigthButton = [[UIBarButtonItem alloc]  initWithTitle:@"编辑"  style:UIBarButtonItemStyleBordered  target:self  action:@selector(editButtonPressed:)];   9.     self.navigationItem.rightBarButtonItem = rigthButton;   10.     [rigthButton release];    11.     //实例化一个可变数组    12.     NSMutableArray *array = [[NSMutableArray alloc] init ];//    13.     self.controllers = array;   14.     [array release];   15.     [self initAllSecondControllers:self.controllers];   16.        17.        18.     // Uncomment the following line to preserve selection between presentations.    19.     // self.clearsSelectionOnViewWillAppear = NO;    20.     21.     // Uncomment the following line to display an Edit button in the navigation bar for this view controller.    22.     // self.navigationItem.rightBarButtonItem = self.editButtonItem;    23. }   - (void)viewDidLoad { [super viewDidLoad]; self.title = @"第一级视图"; // self.navigationItem.title = @"第一级视图";//设置导航控制标题 //实现一个右边按钮,默认顶级视图是没有左右按钮的 UIBarButtonItem *rigthButton = [[UIBarButtonItem alloc] initWithTitle:@"编辑" style:UIBarButtonItemStyleBordered target:self action:@selector(editButtonPressed:)]; self.navigationItem.rightBarButtonItem = rigthButton; [rigthButton release]; //实例化一个可变数组 NSMutableArray *array = [[NSMutableArray alloc] init ];// self.controllers = array; [array release]; [self initAllSecondControllers:self.controllers]; // Uncomment the following line to preserve selection between presentations. // self.clearsSelectionOnViewWillAppear = NO; // Uncomment the following line to display an Edit button in the navigation bar for this view controller. // self.navigationItem.rightBarButtonItem = self.editButtonItem; } 1》导航条的标题有两个方法,设置当前视图得title后,导航条会自动把其当做导航条的title,还有是获取当前视图的导航条控制器,设置title。 2》同理得设置左右按钮也是一样。 顶级视图是不能被pop的,一般呈现形式就是这样。 3.点击一个item后进入二级试图去看看。 整点击进入二级视图就是一个push入一个控制器视图 [cpp] view plaincopyprint? 1. NonoSecondLevelViewController  *secondVC = [self.controllers objectAtIndex:row];   2.    // ...    3.    // Pass the selected object to the new view controller.    4.    [self.navigationController pushViewController:secondVC animated:YES];   NonoSecondLevelViewController *secondVC = [self.controllers objectAtIndex:row]; // ... // Pass the selected object to the new view controller. [self.navigationController pushViewController:secondVC animated:YES]; 默认的,进入二级视图后,导航条就会自动添加一个回退按钮,如果上级视图没有设置title, 按钮得默认文字是“back”,如果设置了title,文字就是这个title。 运用系统默认的样式实现navc基本就是这样,左右键和标题,也能符合我们简单得需求。 对于导航条的样式得修改 系统提供了4中样式 上图设置了bar的style:  //放在window上的根视图     UINavigationController  *nc = [[UINavigationController alloc] init];     [nc.navigationBar setBarStyle:UIBarStyleBlackOpaque]; 一个右边得button; 一个切换或是加载提示框类似于     self.navigationItem.prompt = @"加载"; 在处理完逻辑后,设置成nil就ok了。 对于如何自定义导航条,这个下回等我熟透了代码在整。 IOS学习八:UITableView表视图控件初步 分类: 移动开发_IOS学习 2012-05-04 18:03 856人阅读 评论(1) 收藏 举报 表视图这个控件学习的时候,发现是目前我接触到最复杂的组件。 在Android中也提供了类似表视图的控件叫ListView。 原生的ListView,支持的操作其实很有限,数据的条目展示,点击或是长按的操作。 后来慢慢的衍生出来的索引,分区,动态改变指定条目位置等。 到了IOS发现,原来都是这些设计概念全是从IOS的表视图移植过去的吧。 因此,IOS的表视图是个挺丰富的控件 以下文章内容我基本是这么个流程划分 最简单的表视图——》自定义Cell表——》可编辑表——》可动态移动表 以下是配合Navigation导航条控件演示的tableView各种实现。 一:基础表视图 我们看下表视图一个大致的界面模型 首先是navc的顶级视图 这个视图控制器的代码基本很前面提到的导航那章一样,只是多了一个数组容器来保存要显示的三个二级视图控制器 看下m文件 [cpp] view plaincopyprint? 1. //    2. //  NonoFirstLevelViewController.m    3. //  NavTest    4. //    5. //  Created by Nono on 12-4-26.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import "NonoFirstLevelViewController.h"    10. #import "NonoSecondLevelViewController.h"    11. #import "SimpleTableViewController.h"    12. #import "CustomCellViewController.h"    13. #import "EditViewController.h"    14. @interface NonoFirstLevelViewController ()   15.    16. @end   17.    18. @implementation NonoFirstLevelViewController   19. @synthesize controllers = _controllers;   20. #pragma 实现头文件中自定义方法;    21. - (void)initAllSecondControllers:(NSMutableArray *)array   22. {   23.     SimpleTableViewController *controller1 = [[SimpleTableViewController alloc] init];   24.     [controller1 setTitle:@"简单表视图"];   25.     [array addObject:controller1];   26.     [controller1 release];   27.        28.     CustomCellViewController *controller2 = [[CustomCellViewController alloc] init];   29.      [controller2 setTitle:@"自定义cell视图"];   30.     [array addObject:controller2];   31.     [controller2 release];   32.        33.        34.     EditViewController *controller3 = [[EditViewController alloc] init];   35.     [controller3 setTitle:@"可编辑视图"];   36.     [array addObject:controller3];   37.     [controller3 release];   38. }   39.    40. - (id)initWithStyle:(UITableViewStyle)style   41. {   42.     self = [super initWithStyle:style];   43.     if (self) {   44.     }   45.     return self;   46. }   47.    48. - (void)viewDidLoad   49. {   50.     [super viewDidLoad];   51.     self.title = @"表视图Demo";   52.     //实例化一个可变数组    53.     NSMutableArray *array = [[NSMutableArray alloc] init ];//    54.     self.controllers = array;   55.     [array release];   56.     [self initAllSecondControllers:self.controllers];   57. }   58.    59. - (void)viewDidUnload   60. {   61.     [super viewDidUnload];   62. }   63.    64. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation   65. {   66.     return (interfaceOrientation == UIInterfaceOrientationPortrait);   67. }   68.    69. #pragma mark - Table view data source    70. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section   71. {   72.     return [self.controllers count];   73. }   74.    75. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath   76. {   77.     static NSString *CellIdentifier = @"FirstLevelCell";   78.     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];   79.     if (cell == nil) {   80.         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];   81.     }   82.     NSUInteger row = [indexPath row];   83.     NonoSecondLevelViewController *controller = [self.controllers objectAtIndex:row];   84.     cell.textLabel.text = [controller title];   85.     return cell;   86. }   87.    88. #pragma mark - Table view delegate    89. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath   90. {   91.     NSUInteger row = [indexPath row];   92.     NonoSecondLevelViewController  *secondVC = [self.controllers objectAtIndex:row];   93.      [self.navigationController pushViewController:secondVC animated:YES];   94.         95. }   96.    97. @end   // // NonoFirstLevelViewController.m // NavTest // // Created by Nono on 12-4-26. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "NonoFirstLevelViewController.h" #import "NonoSecondLevelViewController.h" #import "SimpleTableViewController.h" #import "CustomCellViewController.h" #import "EditViewController.h" @interface NonoFirstLevelViewController () @end @implementation NonoFirstLevelViewController @synthesize controllers = _controllers; #pragma 实现头文件中自定义方法; - (void)initAllSecondControllers:(NSMutableArray *)array { SimpleTableViewController *controller1 = [[SimpleTableViewController alloc] init]; [controller1 setTitle:@"简单表视图"]; [array addObject:controller1]; [controller1 release]; CustomCellViewController *controller2 = [[CustomCellViewController alloc] init]; [controller2 setTitle:@"自定义cell视图"]; [array addObject:controller2]; [controller2 release]; EditViewController *controller3 = [[EditViewController alloc] init]; [controller3 setTitle:@"可编辑视图"]; [array addObject:controller3]; [controller3 release]; } - (id)initWithStyle:(UITableViewStyle)style { self = [super initWithStyle:style]; if (self) { } return self; } - (void)viewDidLoad { [super viewDidLoad]; self.title = @"表视图Demo"; //实例化一个可变数组 NSMutableArray *array = [[NSMutableArray alloc] init ];// self.controllers = array; [array release]; [self initAllSecondControllers:self.controllers]; } - (void)viewDidUnload { [super viewDidUnload]; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.controllers count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"FirstLevelCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } NSUInteger row = [indexPath row]; NonoSecondLevelViewController *controller = [self.controllers objectAtIndex:row]; cell.textLabel.text = [controller title]; return cell; } #pragma mark - Table view delegate - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger row = [indexPath row]; NonoSecondLevelViewController *secondVC = [self.controllers objectAtIndex:row]; [self.navigationController pushViewController:secondVC animated:YES]; } @end 顶视图类基本就是一个导航作用。 线面我么先看最简单的这条目 简单表视图: [cpp] view plaincopyprint? 1. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath   2. {   3.     //控件复用    4.     static NSString *CellIdentifier = @"simpleCell";   5.     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];   6.     if (cell == nil) {   7.         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];   8.          9.     }   10.     NSUInteger row = [indexPath row];   11.     NSString *string = [self.data objectAtIndex:row];   12.     cell.textLabel.text = string;   13.        14.     //这个可以定义item右端小图标显示风格,默认是none;    15.     //cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;    16.     [string release];   17.     return cell;   18. }   - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { //控件复用 static NSString *CellIdentifier = @"simpleCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } NSUInteger row = [indexPath row]; NSString *string = [self.data objectAtIndex:row]; cell.textLabel.text = string; //这个可以定义item右端小图标显示风格,默认是none; //cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; [string release]; return cell; } 这边主要说如下几点: 1》。控件得复用,这个和Android很像,因此我们在获取cell对象时,先从原来得复用队列里查找(更具指定的标记,这点也告诉我们,我们可以设置多个标记), 若没有,那就新建一个 2》。整个tableview的style分两种,一种就是顶级视图界面的那种: self.tableView.style = UITableViewStylePlain,另一种就是这个视图的风格: self.tableView.style = UITableViewStyleGrouped 3》.对于每个item,单元格样式使用了3个不同的单元格元素。依次左边开始有个图标,中间就是一个label,右侧会有一个详情栏。 4》。同样的对于每个cell也是有样式风格的 cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] 针对3,4设置后得某种效果如下: 左端可以自己敬爱个图标进去,黑体字就是文本label,灰色的是详细文本标签,小箭头图标是accessoryType 以下就是代码 [cpp] view plaincopyprint? 1. static NSString *CellIdentifier = @"FirstLevelCell";   2. UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];   3. if (cell == nil) {   4.     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];   5. }   6. NSUInteger row = [indexPath row];   7. NonoSecondLevelViewController *controller = [self.controllers objectAtIndex:row];   8. cell.textLabel.text = [controller title];   9. cell.detailTextLabel.text = @"什么情况";   10. //这个可以定义item右端小图标显示风格,默认是none;    11. cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;   12. return cell;   static NSString *CellIdentifier = @"FirstLevelCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease]; } NSUInteger row = [indexPath row]; NonoSecondLevelViewController *controller = [self.controllers objectAtIndex:row]; cell.textLabel.text = [controller title]; cell.detailTextLabel.text = @"什么情况"; //这个可以定义item右端小图标显示风格,默认是none; cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton; return cell; 默认风格的cell是不能显示详情标签内容的。 其实很多效果,代码都走一边就看出来了,具体就自己改动下代码就ok了 二:自定义的Cell 自定义的cell,xib实现 基本没什么好说的,看下该类额控制器文件 [cpp] view plaincopyprint? 1. //    2. //  CustomCellViewController.m    3. //  NavTest    4. //    5. //  Created by Nono on 12-5-4.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import "CustomCellViewController.h"    10.    11. @interface CustomCellViewController ()   12.    13. @end   14. @implementation CustomCellViewController   15. @synthesize customCell = _customCell;   16. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil   17. {   18.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];   19.     if (self) {   20.         // Custom initialization    21.     }   22.     return self;   23. }   24.    25. - (void)viewDidLoad   26. {   27.     [super viewDidLoad];   28.     NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"陈凯",@"Nono",@"Lilith",@"窗前明月光",@"疑是地上霜",@"举头望明月",@"低头思故乡",@"锄禾日当午",@"汗滴禾下土",@"谁知盘中餐",@"粒粒皆幸苦",nil];   29.     self.data = array;   30.     [array release];   31.     // Do any additional setup after loading the view from its nib.    32. }   33.    34. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation   35. {   36.     return (interfaceOrientation == UIInterfaceOrientationPortrait);   37. }   38.    39.    40. #pragma mark_    41. #pragma 数据源方法    42. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section   43. {   44.     return [self.data count];   45.        46. }   47.    48. // Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier:    49. // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls)    50.    51. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath   52. {   53.        54.     static NSString *CellIdentifier = @"CustomCell";   55.     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];   56.     if (cell == nil) {   57.         NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil];   58.         if([nib count] > 0){   59.             cell = self.customCell;   60.             cell.backgroundColor = [UIColor redColor];   61.         }else{   62.             NSLog(@"加载 nib文件失败");   63.         }   64.            65.     }   66.     NSUInteger row = [indexPath row];   67.     NSString *string = [self.data objectAtIndex:row];   68.     UILabel *customlabel =(UILabel*) [cell viewWithTag:11];   69.     customlabel.text = string;   70.     [string release];   71.     return cell;   72. }   73. @end   // // CustomCellViewController.m // NavTest // // Created by Nono on 12-5-4. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "CustomCellViewController.h" @interface CustomCellViewController () @end @implementation CustomCellViewController @synthesize customCell = _customCell; - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"陈凯",@"Nono",@"Lilith",@"窗前明月光",@"疑是地上霜",@"举头望明月",@"低头思故乡",@"锄禾日当午",@"汗滴禾下土",@"谁知盘中餐",@"粒粒皆幸苦",nil]; self.data = array; [array release]; // Do any additional setup after loading the view from its nib. } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); } #pragma mark_ #pragma 数据源方法 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return [self.data count]; } // Row display. Implementers should *always* try to reuse cells by setting each cell's reuseIdentifier and querying for available reusable cells with dequeueReusableCellWithIdentifier: // Cell gets various attributes set automatically based on table (separators) and data source (accessory views, editing controls) - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"CustomCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"CustomCell" owner:self options:nil]; if([nib count] > 0){ cell = self.customCell; cell.backgroundColor = [UIColor redColor]; }else{ NSLog(@"加载 nib文件失败"); } } NSUInteger row = [indexPath row]; NSString *string = [self.data objectAtIndex:row]; UILabel *customlabel =(UILabel*) [cell viewWithTag:11]; customlabel.text = string; [string release]; return cell; } @end 提几个注意点: 1》。cell的xib文件得拥有者设置成该类,在该类得头文件中定义一个输出口。 2》 我们看到cell的xib文件有3个label视图我们能看到,其实还有一个没有title的label视图,也就我们要动态添加数据的那个视图, 在xib文件中需要给他设置一个tag,这样我们在代码里才能根据tag找出该对象(和Android中得id很像)。这边我定义了11,所以  UILabel *customlabel =(UILabel*) [cellviewWithTag:11];     customlabel.text = string; 3》。xib文件加载,我是根据书上得列子方法。根据应用的束来获取。 4》。哦,还有点就是 static NSString *CellIdentifier = @"CustomCell";。这个在xib文件得指定器中定义,因为原本我们新建一个cell是有个传入指定标签, 而现在这个新建一个cell说白了就是直接从xib中加载一个实例化了,那么指定器怎需要在xib中定义下。 对于cell简单的自定义就是这样。 三:可编辑的tableView(删除,添加,移动) [cpp] view plaincopyprint? 1. //    2. //  EditViewController.m    3. //  NavTest    4. //    5. //  Created by Nono on 12-5-4.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import "EditViewController.h"    10.    11. @interface EditViewController ()   12.    13. @end   14.    15. @implementation EditViewController   16. @synthesize edittableView;   17. - (void)editButtonPressed:(id)sender   18. {      19.     [self.edittableView setEditing:!self.edittableView.editing animated:(YES)];   20.     if (edittableView.editing) {   21.         [self.navigationItem.rightBarButtonItem setTitle:@"完成"];   22.     }else {   23.         [self.navigationItem.rightBarButtonItem setTitle:@"编辑"];   24.     };   25.     NSLog(@"点击了按钮");   26. }   27. - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil   28. {   29.     self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];   30.     if (self) {   31.         // Custom initialization    32.     }   33.     return self;   34. }   35.    36. - (void)viewDidLoad   37. {   38.     [super viewDidLoad];   39.     NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"陈凯",@"Nono",@"Lilith",@"窗前明月光",@"疑是地上霜",@"举头望明月",@"低头思故乡",@"锄禾日当午",@"汗滴禾下土",@"谁知盘中餐",@"粒粒皆幸苦",nil];   40.     self.data = array;   41.     [array release];   42.     UIBarButtonItem *rigthButton = [[UIBarButtonItem alloc]  initWithTitle:@"编辑"  style:UIBarButtonItemStyleBordered  target:self  action:@selector(editButtonPressed:)];   43.     self.navigationItem.rightBarButtonItem = rigthButton;   44.     //self.navigationItem.prompt = @"加载";    45.     [rigthButton release];    46.     // Do any additional setup after loading the view from its nib.    47. }   48.    49. - (void)viewDidUnload   50. {   51.     [super viewDidUnload];   52.     // Release any retained subviews of the main view.    53.     // e.g. self.myOutlet = nil;    54. }   55.    56. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation   57. {   58.     return (interfaceOrientation == UIInterfaceOrientationPortrait);   59. }   60.    61. #pragma mark - Table view data source    62.    63. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section   64. {   65.     // Return the number of rows in the section.    66.     return [self.data count];   67. }   68.    69. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath   70. {   71.     static NSString *CellIdentifier = @"editLevelCell";   72.     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];   73.     if (cell == nil) {   74.         cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];   75.     }   76.     NSUInteger row = [indexPath row];   77.     NSString *string = [self.data objectAtIndex:row];   78.     cell.textLabel.text = string;   79.     [string release];   80.     return cell;   81. }   82.    83. #pragma 实现数据源协议中一些关于编辑操作方法    84. - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath   85. {   86.     //是否可以编辑,即是tableView setEditing的前提;默认是yes,实现这个方法估计主要是选择性的编辑条目。    87.     return YES;   88. }   89.    90. - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath   91. {   92.     //同理默认其实就是yes,移动模式(会显示可以触摸得移动button)必须是在实现了下面这个方法才有效,否则及时yes了,移动模式条也是不显示的,简单的说,你不能执行移动操作    93.     return YES;   94. }   95. //移动操作    96. - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath   97. {   98.     //拖动得思路就是先备份选中行,删除原来那份,将备份的一份插入到目标行    99.     NSUInteger fromRow = [sourceIndexPath row];   100.     NSUInteger toRow = [destinationIndexPath row];   101.     id ob = [[self.data objectAtIndex:fromRow] retain];   102.     [self.data removeObjectAtIndex:fromRow];   103.     [self.data insertObject:ob atIndex:toRow];   104.     [ob release];   105. }   106.    107. - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath   108. {   109.       NSUInteger row = [indexPath row];   110.     //提交操作完的编辑    111.     if (editingStyle == UITableViewCellEditingStyleDelete) {   112.         [self.data removeObjectAtIndex:row]; //删除操作    113.         [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];   114.     }   115.        116.     if (editingStyle == UITableViewCellEditingStyleInsert) {   117.         [self.data insertObject:@"插入数据" atIndex:row];//插入操作    118.         [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft];   119.     }    120. }   121.    122. #pragma 实现tableView委托中一些方法    123. - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath;   124. {   125.     //设置可编辑得样式:系统提供了三种,一种是删除,一种是插入,一种时是none    126.     NSInteger row = [indexPath row];   127.     if(row %2 == 0)//这边做了小处理,间隔显示删除和插入    128.     {   129.         return UITableViewCellEditingStyleDelete;   130.     }   131.     return UITableViewCellEditingStyleInsert;   132. }   133. @end   // // EditViewController.m // NavTest // // Created by Nono on 12-5-4. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "EditViewController.h" @interface EditViewController () @end @implementation EditViewController @synthesize edittableView; - (void)editButtonPressed:(id)sender { [self.edittableView setEditing:!self.edittableView.editing animated:(YES)]; if (edittableView.editing) { [self.navigationItem.rightBarButtonItem setTitle:@"完成"]; }else { [self.navigationItem.rightBarButtonItem setTitle:@"编辑"]; }; NSLog(@"点击了按钮"); } - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; if (self) { // Custom initialization } return self; } - (void)viewDidLoad { [super viewDidLoad]; NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:@"陈凯",@"Nono",@"Lilith",@"窗前明月光",@"疑是地上霜",@"举头望明月",@"低头思故乡",@"锄禾日当午",@"汗滴禾下土",@"谁知盘中餐",@"粒粒皆幸苦",nil]; self.data = array; [array release]; UIBarButtonItem *rigthButton = [[UIBarButtonItem alloc] initWithTitle:@"编辑" style:UIBarButtonItemStyleBordered target:self action:@selector(editButtonPressed:)]; self.navigationItem.rightBarButtonItem = rigthButton; //self.navigationItem.prompt = @"加载"; [rigthButton release]; // Do any additional setup after loading the view from its nib. } - (void)viewDidUnload { [super viewDidUnload]; // Release any retained subviews of the main view. // e.g. self.myOutlet = nil; } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation == UIInterfaceOrientationPortrait); } #pragma mark - Table view data source - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { // Return the number of rows in the section. return [self.data count]; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"editLevelCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease]; } NSUInteger row = [indexPath row]; NSString *string = [self.data objectAtIndex:row]; cell.textLabel.text = string; [string release]; return cell; } #pragma 实现数据源协议中一些关于编辑操作方法 - (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath { //是否可以编辑,即是tableView setEditing的前提;默认是yes,实现这个方法估计主要是选择性的编辑条目。 return YES; } - (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath { //同理默认其实就是yes,移动模式(会显示可以触摸得移动button)必须是在实现了下面这个方法才有效,否则及时yes了,移动模式条也是不显示的,简单的说,你不能执行移动操作 return YES; } //移动操作 - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath { //拖动得思路就是先备份选中行,删除原来那份,将备份的一份插入到目标行 NSUInteger fromRow = [sourceIndexPath row]; NSUInteger toRow = [destinationIndexPath row]; id ob = [[self.data objectAtIndex:fromRow] retain]; [self.data removeObjectAtIndex:fromRow]; [self.data insertObject:ob atIndex:toRow]; [ob release]; } - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { NSUInteger row = [indexPath row]; //提交操作完的编辑 if (editingStyle == UITableViewCellEditingStyleDelete) { [self.data removeObjectAtIndex:row]; //删除操作 [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; } if (editingStyle == UITableViewCellEditingStyleInsert) { [self.data insertObject:@"插入数据" atIndex:row];//插入操作 [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationLeft]; } } #pragma 实现tableView委托中一些方法 - (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath; { //设置可编辑得样式:系统提供了三种,一种是删除,一种是插入,一种时是none NSInteger row = [indexPath row]; if(row %2 == 0)//这边做了小处理,间隔显示删除和插入 { return UITableViewCellEditingStyleDelete; } return UITableViewCellEditingStyleInsert; } @end 基本代码如上。 发现写的太长了。。哎 下班回家~ IOS学习九:ios开发之数据的持久化存储机制 分类: 移动开发_IOS学习 2012-05-13 10:12 1606人阅读 评论(3) 收藏 举报 IOS中数据的持久化保存这块内容,类似于Android中文件的几种常见的存储方式。 对于数据的持久化存储,ios中一般提供了4种不同的机制。 1.属性列表 2.对象归档 3.数据库存储(SQLite3) 4.苹果公司提供的持久性工具Core Data。 其实储存的形式无非就这么几种,而我们还必须要关心的是,这些文件会被放置在那个文件下,然后如何读取。 也就是说:IOS上数据存储,我们要了解的两点,数据存储格式(也就是存储机制),数据存储位置。 1》文件如何存储(如上面4点) 2》文件存储在哪里。 对于数据的操作,其实我们关心的是操作的速率。 就好比在Adnroid中偏好存储,数据库存储,io存储一样。 我大致问了我们公司新来的ios哥们,他说他们培训机构基本对数据操作这块就讲了属性列表和数据库,以及普通的文件存储(比如音视频图这些多媒体数据)。 我就只好先看看书了。 一:应用文件目录 首先我们来看了解下ios数据存储位置,因为只有知道位置路径我们才能去读取数据,而数据的持久化机制不过是针对操作速率来考虑的, 比如我们大致知道属性列表(既键值对形式)的存储熟虑应该高于数据库高于io文件流存储。 我们在选择用何种机制存储数据,主要也是看数据的形式。 一个ios应用安装后大致会有如下文件夹及其对应路径: 在mac上看模拟器中应用路径: /Users/nono/Library/Application Support/iPhone Simulator/5.1/Applications/2D135859-1E80-4754-B36D-34A53C521DE3 你在finder中的home下可能找不到Library这个目录,因为貌似是影藏起来了(我这机器上是,在终端可以看到)。 最后那一窜的类似序列号的东西就是ios自动给应用生成的一组应用唯一识别码最为了应用的home目录名。 其下面就是上图所示了。 书上对这些文件夹介绍: Document:应用程序将其数据存储在这个文件夹下,基于NSUserDefaults的首选项的设置除外。 简单理解是,基本上我们要操作的一些数据都是存储在这个文件夹下面的 TIPS:这边提下一点,对于ios系统这么分配文件夹,是因为在设备进行同步时,ITunes有选择性的意识来备份文件。 比如我们可以猜到,tmp下的应该就不会备份了。 对于Document文件夹目录路径的获取,API提供了这么一种方法: [cpp] view plaincopyprint? 1. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);   2.    NSString *docPath = [paths objectAtIndex:0];   NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docPath = [paths objectAtIndex:0]; Library:基于NSUserDefault首选项设置存储在其下Preferences文件夹中,简单来说,这个文件夹一般你很少操作到。 书上对于这部分基本没介绍。估计对于初级部分是跳过了。 Tmp:应用临时存储文件,当不需要时,应用负责删除其下的文件数据。 该文件也提供了目录获取方法: [cpp] view plaincopyprint? 1. NSString *tmpDoc = NSTemporaryDirectory();   NSString *tmpDoc = NSTemporaryDirectory(); 应用程序文件:这个基本没提到书上,但是我们大致可以猜测,这就是整个应用程序的程序文件夹吧。 好了,以上我们大致解决了我们提到的第一个点,文件存储目录 二:数据存储机制 1.属性列表 这个其实我们早见过,plist就是,感觉用来存储键值对小数据是最合适,因为速率很高。 这个存储机制很简单,对于前面我们使用过了在plist文件来读取数据填充一些列表,只不过那会plist文件存储位置不同, 用的是Mainbundle什么的来返回文件夹,其实这边我也推测,上面提到有个应用程序文件夹,它下面的文件就是这么来读取的~(反正暂时不管他) 这边不过就是改变了存储位置,数据操作还是一样的 [cpp] view plaincopyprint? 1. NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);   2. NSString *docPath = [paths objectAtIndex:0];   3. NSString *myFile = [docPath stringByAppendingPathComponent:@"my.list"];   4. //读取文件    5. NSArray *array = [[NSArray alloc] initWithContentsOfFile:myFile];   6. //操作完若修改了数据则,写入文件    7. [array writeToFile:myFile atomically:YES];   NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); NSString *docPath = [paths objectAtIndex:0]; NSString *myFile = [docPath stringByAppendingPathComponent:@"my.list"]; //读取文件 NSArray *array = [[NSArray alloc] initWithContentsOfFile:myFile]; //操作完若修改了数据则,写入文件 [array writeToFile:myFile atomically:YES]; 2.对象归档 上面的属性列表存储机制,我们都知道,这个机制支持NSArray,NSDictionary,NSData,NSString,NSNumber,NSDate 等等 这些对象直接写入plist文件中。 那么对于一些复杂对象,我要保存整个这个对象数据呢? 反正我是这么觉得,这个机制很像java中的对象整体序列化。当然,这些数据在读取是就需要遵循一种墨守成规的协议了。 首先我们定义的对象类,必须实现NSCoding和NSCopying协议(额,网上说后面这个不实现也可以,我猜是他对象没有copy操作,因此没出错)书本上反正是实现了这两个协议 然后归档中用到的操作类 NSKeyedArchiver 这边我们定义一个对象,h文件中定义两属性,申明要实现的NSCoding和NSCopying协议 实现文件 [cpp] view plaincopyprint? 1. //    2. //  TestObj.m    3. //  DataStorageTest    4. //    5. //  Created by Nono on 12-5-12.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import "TestObj.h"    10.    11. @implementation TestObj   12. @synthesize stringA = stringA;   13. @synthesize stringB = stringB;   14.    15. #pragma mark -    16. #pragma NSCoding协议实现实现    17. - (void)encodeWithCoder:(NSCoder *)aCoder   18. {   //encoder    19.     [aCoder encodeObject:stringAforKey:@"1"];   20.     [aCoder encodeObject:stringBforKey:@"2"];   21. }   22. - (id)initWithCoder:(NSCoder *)aDecoder   23. {   24.     //decoder    25.     if (self = [superinit]) {   26.         stringA = [[aDecoder decodeObjectForKey:@"1"] retain];   27.         stringB = [[aDecoder decodeObjectForKey:@"2"] retain];   28.     }   29.     returnself;   30. }   31.    32. #pragma NSCopying协议实现    33. - (id)copyWithZone:(NSZone *)zone   34. {   35.     TestObj *copy = [[[selfclass] allocWithZone:zone] init];   36.     copy.stringA = [[self.stringAcopyWithZone:zone] autorelease];   37.     copy.stringB = [[self.stringBcopyWithZone:zone] autorelease];   38.     return copy;   39. }   40. @end   // // TestObj.m // DataStorageTest // // Created by Nono on 12-5-12. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "TestObj.h" @implementation TestObj @synthesize stringA = stringA; @synthesize stringB = stringB; #pragma mark - #pragma NSCoding协议实现实现 - (void)encodeWithCoder:(NSCoder *)aCoder { //encoder [aCoder encodeObject:stringAforKey:@"1"]; [aCoder encodeObject:stringBforKey:@"2"]; } - (id)initWithCoder:(NSCoder *)aDecoder { //decoder if (self = [superinit]) { stringA = [[aDecoder decodeObjectForKey:@"1"] retain]; stringB = [[aDecoder decodeObjectForKey:@"2"] retain]; } returnself; } #pragma NSCopying协议实现 - (id)copyWithZone:(NSZone *)zone { TestObj *copy = [[[selfclass] allocWithZone:zone] init]; copy.stringA = [[self.stringAcopyWithZone:zone] autorelease]; copy.stringB = [[self.stringBcopyWithZone:zone] autorelease]; return copy; } @end 然后是对对象归档的读取和写入 [cpp] view plaincopyprint? 1. //读取归档文件    2.    NSData *data = [[NSMutableDataalloc] initWithContentsOfFile:myFile];   3.    NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiveralloc] initForReadingWithData:data];   4.    TestObj * test = [unarchiver decodeObjectForKey:@"data"];   5.    [unarchiver finishDecoding];   6.    [data release];   7.    [unarchiver release];   8.       9.    //写入归档文件    10.    NSMutableData *data1 = [[NSMutableDataalloc] init];   11.    NSKeyedArchiver *archiver = [[NSKeyedArchiveralloc] initForWritingWithMutableData:data1];   12.    [archiver encodeObject:test forKey:@"data"];   13.    [archiver finishEncoding];   14.    [data writeToFile:myFile atomically:YES];   15.    [data1 release];   16.    [archiver release];   17.    [test release];   //读取归档文件 NSData *data = [[NSMutableDataalloc] initWithContentsOfFile:myFile]; NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiveralloc] initForReadingWithData:data]; TestObj * test = [unarchiver decodeObjectForKey:@"data"]; [unarchiver finishDecoding]; [data release]; [unarchiver release]; //写入归档文件 NSMutableData *data1 = [[NSMutableDataalloc] init]; NSKeyedArchiver *archiver = [[NSKeyedArchiveralloc] initForWritingWithMutableData:data1]; [archiver encodeObject:test forKey:@"data"]; [archiver finishEncoding]; [data writeToFile:myFile atomically:YES]; [data1 release]; [archiver release]; [test release]; 但是问了下新同事,据说这个用到也是蛮少,至少他目前。 但是,我看了下,觉得这个和Android 中Parcelable 太尼玛像似了 三.数据库存储 和Android一样,ios中也是用了SQLite3这种嵌入式数据库。 这个网上例子是很多了。我这边就大致看下了数据库的打开, 数据库表创建,查询,插入 [cpp] view plaincopyprint? 1.  //数据库操作    2.  sqlite3 *database;   3. // const NSString * dbname = @"mydb"    4.  int result;   5.  //打开一个指定路径的现有的数据库,如果没有则会新建一个db库    6.  result =  sqlite3_open([myFile UTF8String], &database);   7.  if (result != SQLITE_OK) {   8.      sqlite3_close(database);   9.  }   10.     11.  //创建一个db表    12.  char *errorMsg;   13.  NSString *sql_create_table = @"CREATE TABLE IF NOT EXISTS NONOTABLE 省略~~~~~~~~~~~~~";   14.  int result1 ;   15.  //sqlite_exec用了针对sqlite3运行任何不要返回数据的命令,它用于执行更新,插入和删除。简单来说,这个方法执行的都是一些无需返回数据(虽然我们可能获取一个状态值。)。    16.  result1 = sqlite3_exec(database, [sql_create_table UTF8String], NULL, NULL, &errorMsg);   17.     18.  //检索查询操作    19.  int result2 ;   20.  sqlite3_stmt *statment;   21.  NSString *sql_selected = @"查询语句";   22. result2 = sqlite3_prepare_v2(database, [sql_selected UTF8String], -1, &statment, nil);   23.  if(result2 == SQLITE_OK){   24.      //单步操作    25.      while (sqlite3_step(statment) == SQLITE_ROW) {   26.          int row = sqlite3_column_int(statment, 0);   27.          char * rpwData = sqlite3_column_text(statment, 1);     28.      }   29.      sqlite3_finalize(statment);   30.  }   31.     32.     33.  //绑定变量,既就是插入操作的一种变种,比如我么那上面提到sqlite_exec可以执行插入操作,插入内容直接是写在sql字窜里,但是考虑到字窜涉及到无效的符号以及会一些严重的注入漏洞(比如以前听过的引号符号)。    34.  NSString *sql_bind = @"insert into foo value(?,?)";   35.  result2 = sqlite3_prepare_v2(database, [sql_selected UTF8String], -1, &statment, nil);   36.  if(result2 == SQLITE_OK){   37.      sqlite3_bind_int(statment, 1, 235);   38.      sqlite3_bind_text(statment, 2, "test", -1, nil);   39.            sqlite3_finalize(statment);   40.  }   41.  if (sqlite3_step(statment) != SQLITE_DONE)   42.      NSLog(@"error");   43.  sqlite3_finalize(statment);   44.    45.    46.  sqlite3_close(database);   //数据库操作 sqlite3 *database; // const NSString * dbname = @"mydb" int result; //打开一个指定路径的现有的数据库,如果没有则会新建一个db库 result = sqlite3_open([myFile UTF8String], &database); if (result != SQLITE_OK) { sqlite3_close(database); } //创建一个db表 char *errorMsg; NSString *sql_create_table = @"CREATE TABLE IF NOT EXISTS NONOTABLE 省略~~~~~~~~~~~~~"; int result1 ; //sqlite_exec用了针对sqlite3运行任何不要返回数据的命令,它用于执行更新,插入和删除。简单来说,这个方法执行的都是一些无需返回数据(虽然我们可能获取一个状态值。)。 result1 = sqlite3_exec(database, [sql_create_table UTF8String], NULL, NULL, &errorMsg); //检索查询操作 int result2 ; sqlite3_stmt *statment; NSString *sql_selected = @"查询语句"; result2 = sqlite3_prepare_v2(database, [sql_selected UTF8String], -1, &statment, nil); if(result2 == SQLITE_OK){ //单步操作 while (sqlite3_step(statment) == SQLITE_ROW) { int row = sqlite3_column_int(statment, 0); char * rpwData = sqlite3_column_text(statment, 1); } sqlite3_finalize(statment); } //绑定变量,既就是插入操作的一种变种,比如我么那上面提到sqlite_exec可以执行插入操作,插入内容直接是写在sql字窜里,但是考虑到字窜涉及到无效的符号以及会一些严重的注入漏洞(比如以前听过的引号符号)。 NSString *sql_bind = @"insert into foo value(?,?)"; result2 = sqlite3_prepare_v2(database, [sql_selected UTF8String], -1, &statment, nil); if(result2 == SQLITE_OK){ sqlite3_bind_int(statment, 1, 235); sqlite3_bind_text(statment, 2, "test", -1, nil); sqlite3_finalize(statment); } if (sqlite3_step(statment) != SQLITE_DONE) NSLog(@"error"); sqlite3_finalize(statment); sqlite3_close(database); 关于更多的,大伙可以自行百度,因为数据库的操作语法太怪异了,书上说是基本是基于c的,本人没学过c。看得有点心烦~ 4。Core Data存储机制 大致浏览下基本感觉就是将对象归档搞成了可视化和简单化。 这块内容比较多。网上资料也挺丰富的。 暂时不做介绍了。 总结下:其实对于ios数据存储,最常用和主要要掌握的就是属性列表和数据库,因为两个是出镜率比较高的。 其他可能在数据存明显体现出储优势时,我们会去考虑用另外两种机制。 基础的来说,必须掌握属性列表和sqlite的操作存储。 IOS学习十一:ios开发之网络编程 分类: 移动开发_IOS学习 2012-05-21 11:15 635人阅读 评论(0) 收藏 举报 上周末本应早写这个网络和MapKit的。 由于周六朋友聚会,周日送一朋友回远方,吃吃喝喝的就忘掉了。 网络编程基本是移动互联这块中必须掌握的编程技巧。由于我买的的小柚子书上没有这块, 最近刚买的开发秘籍那本上的关于网络链接这块,太抽象了。 首先吐槽一下这本书,细节描述的还是不错的。但是不合适做入门~ 然后在网络上搜索关于ios的网络编程基本就首页全是讲的同一篇文章,被转烂了。 找了半天没找到源文出处。 可以参考的一个地址:http://www.cocoachina.com/bbs/read.php?tid-31300.html 主要将了两部分:1.网络检测;2.简单的NSURLConnection链接以及设置代理。 问了下朋友,基本说现在都用 HTTP包装开源项目ASIHTTPRequest。 但这边我们还是从最原始的框架提供的API入手,后边我再去看下这个。 这边我就以最简单的例子来引入几个常用的API中的类。 [cpp] view plaincopyprint? 1. //    2. //  NLViewController.m    3. //  NetWorkTest    4. //    5. //  Created by Nono on 12-5-16.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8. #import "NLViewController.h"    9.    10. @interface NLViewController ()   11.    12. @end   13.    14. @implementation NLViewController   15. @synthesize label = _label;   16. @synthesize data = _data;   17. @synthesize connection = _connection;   18. - (void)dealloc{   19.     [self.label release];   20.     [self.data release];   21.     [super dealloc];   22. }   23. - (void)viewDidLoad   24. {   25.     [super viewDidLoad];   26.     UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 10.0, 300.0, 400)];   27.     self.label = label;   28.     label.textAlignment = UITextAlignmentCenter;   29.     [label setNumberOfLines:0];   30.     label.lineBreakMode = UILineBreakModeWordWrap;    31.     self.label.text = @"正在在请求数据";   32.     [self.view addSubview:label];   33.     [label release];   34.     //step 1:请求地址    35.     NSString *urlString = @"http://www.google.com";   36.     NSURL *url = [NSURL URLWithString:urlString];   37.     //step 2:实例化一个request    38.     NSURLRequest *requrst = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];   39.     //step 3:创建链接    40.     self.connection = [[NSURLConnection alloc] initWithRequest:requrst delegate:self];   41.     if ( self.connection) {   42.         NSLog(@"链接成功");   43.     }else {   44.         NSLog(@"链接失败");   45.     }   46.        47.     [url release];   48.     [urlString release];   49.     [requrst release];   50.     // Do any additional setup after loading the view, typically from a nib.    51. }   52.    53. - (void)viewDidUnload   54. {   55.     self.label = nil;   56.     self.data = nil;   57.     [super viewDidUnload];   58.     // Release any retained subviews of the main view.    59. }   60.    61. - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation   62. {   63.     return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);   64. }   65.    66. #pragma mark-    67. #pragma NSUrlConnectionDelegate methods    68. - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response   69. {   70.     //接受一个服务端回话,再次一般初始化接受数据的对象    71.       72.     NSLog(@"返回数据类型:%@",[response textEncodingName]);    73.     NSMutableData *d = [[NSMutableData alloc] init];   74.      self.data = d;   75.     [d release];   76. }   77.    78. - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data   79. {   80.     //接受返回数据,这个方法可能会被调用多次,因此将多次返回数据加起来    81.        82.     NSUInteger datalength = [data length];   83.     NSLog(@"返回数据量:%d",datalength);   84.     [self.data appendData:data];   85. }   86.    87. - (void)connectionDidFinishLoading:(NSURLConnection *)connection   88. {   89.     //连接结束    90.        91.     NSLog(@"%d:",[self.data length]);   92.     NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);   93.     NSString *mystr = [[NSString alloc] initWithData:_data encoding:enc];   94.    // string i    95.     NSLog(@"最后的结果:%@",mystr);   96.     self.label.text = mystr;   97.     [mystr release];   98.     [self.connection release];   99. }   100.    101. - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error   102. {   103.     //链接错误    104. }   105.    106. @end   // // NLViewController.m // NetWorkTest // // Created by Nono on 12-5-16. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "NLViewController.h" @interface NLViewController () @end @implementation NLViewController @synthesize label = _label; @synthesize data = _data; @synthesize connection = _connection; - (void)dealloc{ [self.label release]; [self.data release]; [super dealloc]; } - (void)viewDidLoad { [super viewDidLoad]; UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 10.0, 300.0, 400)]; self.label = label; label.textAlignment = UITextAlignmentCenter; [label setNumberOfLines:0]; label.lineBreakMode = UILineBreakModeWordWrap; self.label.text = @"正在在请求数据"; [self.view addSubview:label]; [label release]; //step 1:请求地址 NSString *urlString = @"http://www.google.com"; NSURL *url = [NSURL URLWithString:urlString]; //step 2:实例化一个request NSURLRequest *requrst = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0]; //step 3:创建链接 self.connection = [[NSURLConnection alloc] initWithRequest:requrst delegate:self]; if ( self.connection) { NSLog(@"链接成功"); }else { NSLog(@"链接失败"); } [url release]; [urlString release]; [requrst release]; // Do any additional setup after loading the view, typically from a nib. } - (void)viewDidUnload { self.label = nil; self.data = nil; [super viewDidUnload]; // Release any retained subviews of the main view. } - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation { return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); } #pragma mark- #pragma NSUrlConnectionDelegate methods - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response { //接受一个服务端回话,再次一般初始化接受数据的对象 NSLog(@"返回数据类型:%@",[response textEncodingName]); NSMutableData *d = [[NSMutableData alloc] init]; self.data = d; [d release]; } - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { //接受返回数据,这个方法可能会被调用多次,因此将多次返回数据加起来 NSUInteger datalength = [data length]; NSLog(@"返回数据量:%d",datalength); [self.data appendData:data]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { //连接结束 NSLog(@"%d:",[self.data length]); NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000); NSString *mystr = [[NSString alloc] initWithData:_data encoding:enc]; // string i NSLog(@"最后的结果:%@",mystr); self.label.text = mystr; [mystr release]; [self.connection release]; } - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { //链接错误 } @end 简单说下: 1.最简单的网络链接,一个url,一个request,一个connection以及一个response返回。默认的是get请求。 2.data转码问题,这个一开始有点纠结。即,在最后我们要把NSData转化成NSString时候需要一个转码格式,一开始我习惯性的用了UTF-8, 然后发现转化后String 是Null,于是去打印了下请求返回的一些参数,显示的是GB2312~。 然后NSStringEncoding enc = CFStringConvertEncodingToNSStringEncoding(kCFStringEncodingGB_18030_2000);     NSString *mystr = [[NSString alloc] initWithData:_data encoding:enc]; 就ok了。 4.代理方法的实现,基本以上几个都需要实现吧。还有更多可选方法可以根据自身需要去选择性实现。 但是,显然,以上这个小例子真的太基础,可能根本不能满足我们的需求,至少得有个post的列子。 然后我看了几个勉强有网络链接demo,写的比较随意化,最后在 ios  developer 中找到一个官方版的比较文正规范的例子。 http://developer.apple.com/library/ios/#samplecode/SimpleURLConnections/Introduction/Intro.html#//apple_ref/doc/uid/DTS40009245 这边也提下,官网的例子很多,也都比较规范化,我们新入门者可以多多参考。 基本上面一个例子就对sdk自带的网络api学习就算完整了。 在加上上面那个提及到的网络检测,至少,现在我们对网络这块有个大致了解。 如果想要自己考虑到上传,下载,像java自己去封装一个网络库。那就多研究下开源库。 据说上面提到那个库很强大,很简洁,也很容易入门 我这边只是简单介绍了网络开发这块几个入门点和入门资料。 有不足忘指出。 还有,哪位大神能帮我比较详细的解答下这个问题 http://www.cocoachina.com/bbs/read.php?tid=103569 IOS学习之十二:Core Location定位和MapKit视图使用 分类: 移动开发_IOS学习 2012-05-22 14:06 717人阅读 评论(0) 收藏 举报 iPhone中的基于位置服务开发的应用其实挺多的。 但是那种能显示密集型周边的信息或者说是资料数据的应用, 还真不知道是通过的是类似于webService还是内置类似于地图导航功能的数据包。 但是对于简单如何上手这方面的开始,我们还是要接触下的。 总的来说,我们这类应用的会涉及到核心的两块内容。 1.位置定位(最简单就是当前应用所有者所持设备的地理位置),主要用到的API类 CLLicationManager。 在其他比如(Android位置类开发),我们知道实现定位的方式有gprs,网络,蜂窝式,基站等。并且是可以通过自己选的。 ios中就却直接hide或者说是简单化了这种定位方式。 只需我们设置一些参数后,系统自动会做出最切当的反应。 2.位置确定了,那么下一步就是显示给用户了。显示的视图,这边用到API类MapKit。 比如我们定位了一个经度 30.002,纬度为199.232.最简单的,我们直接在提供的视图上定位到这个点。 但是我们知道,更多的时候,我们希望显示这个点的更多数据信息(比如街道,XXX路),更甚至是周边的。 这个就需要庞大的数据包支持了,因为我没做过这方面的,只是简单知道可以通过google公开的一个web端接口获取数据。 一:首先简单介绍下CLLicationManager类的常用 开启定位服务: [cpp] view plaincopyprint? 1. self.locationManager = [[CLLocationManager alloc]init];   2.     if (![CLLocationManager locationServicesEnabled]) {   3.         NSLog(@"定位不可用~");   4.            5.     }else {   6.         //设置代理    7.         [self.locationManager setDelegate:self];   8.         //设置精准度,    9.         [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest];   10.         [self.locationManager startUpdatingLocation];   11.     }   self.locationManager = [[CLLocationManager alloc]init]; if (![CLLocationManager locationServicesEnabled]) { NSLog(@"定位不可用~"); }else { //设置代理 [self.locationManager setDelegate:self]; //设置精准度, [self.locationManager setDesiredAccuracy:kCLLocationAccuracyBest]; [self.locationManager startUpdatingLocation]; } 初始化了位置管理器,判断设备的定位功能是否开启开启的话设置代理,精度等参数后,开始服务。 实现代理类方法,获取返回参数: [cpp] view plaincopyprint? 1. #pragma mark-    2. #pragma locationManagerDelegate methods    3. - (void)locationManager:(CLLocationManager *)manager   4.     didUpdateToLocation:(CLLocation *)newLocation   5.            fromLocation:(CLLocation *)oldLocation   6. {   7.     self.coordinate = [newLocation coordinate];   8.     self.altitude = [newLocation altitude];   9.     NSString *lat = [[NSString alloc] initWithFormat:@"%f",self.coordinate.latitude];   10.     NSString *lon = [[NSString alloc] initWithFormat:@"%f",self.coordinate.longitude];   11.     NSString *alt = [[NSString alloc] initWithFormat:@"%f",self.altitude];   12.    13.     //更新定位信息方法    14.     NSLog(@"delegate %f,%f",self.coordinate.latitude,self.coordinate.longitude);   15.     self.latitudeText.text = lat;   16.     self.longitudeText.text = lon;   17.     self.altitudeText.text = alt;   18.        19.     [lat release];   20.     [lon release];   21.     [alt release];   22. }   23.    24. - (void)locationManager:(CLLocationManager *)manager   25.        didFailWithError:(NSError *)error   26. {   27.     //定位失败    28.        29. }   #pragma mark- #pragma locationManagerDelegate methods - (void)locationManager:(CLLocationManager *)manager didUpdateToLocation:(CLLocation *)newLocation fromLocation:(CLLocation *)oldLocation { self.coordinate = [newLocation coordinate]; self.altitude = [newLocation altitude]; NSString *lat = [[NSString alloc] initWithFormat:@"%f",self.coordinate.latitude]; NSString *lon = [[NSString alloc] initWithFormat:@"%f",self.coordinate.longitude]; NSString *alt = [[NSString alloc] initWithFormat:@"%f",self.altitude]; //更新定位信息方法 NSLog(@"delegate %f,%f",self.coordinate.latitude,self.coordinate.longitude); self.latitudeText.text = lat; self.longitudeText.text = lon; self.altitudeText.text = alt; [lat release]; [lon release]; [alt release]; } - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error { //定位失败 } 返回的一个CLLocation 类型包含常用的几种数据,经纬度,运动速率,海拔,方向等,我们可以按需要来获取。 二:用MapKit来显示 第一步就是添加一个mapView视图 然后也是很简单的几行代码即显示位置点。 对于将经纬度转化成友善的地理信息,首先我们来看个最传统的例子,既我们将获取的经纬度封装成一个网络请求到google的map服务, 返回对应的地址信息。 [cpp] view plaincopyprint? 1. latNum = [[NSNumber alloc] initWithFloat:lat];   2. lonNum = [[NSNumber alloc] initWithFloat:lon];   3.      4.  NSURL * aurl = [NSURL URLWithString:[NSString stringWithFormat:   5.                                       @"http://ditu.google.com/maps/geo?q=%@,%@&output=json&oe=utf8&hl=zh-CN&sensor=false",latNum,lonNum]];   6.  NSURLRequest *request = [[NSURLRequest alloc] initWithURL:aurl];   7.  self.connection1=[NSURLConnection connectionWithRequest:request delegate:self];   latNum = [[NSNumber alloc] initWithFloat:lat]; lonNum = [[NSNumber alloc] initWithFloat:lon]; NSURL * aurl = [NSURL URLWithString:[NSString stringWithFormat: @"http://ditu.google.com/maps/geo?q=%@,%@&output=json&oe=utf8&hl=zh-CN&sensor=false",latNum,lonNum]]; NSURLRequest *request = [[NSURLRequest alloc] initWithURL:aurl]; self.connection1=[NSURLConnection connectionWithRequest:request delegate:self]; 请求很简单,将经纬度放置进请求中。 上后上面就是一个传统的网络请求吧, 然后我们在NSURLConnection的代理方法中处理返回数据 [cpp] view plaincopyprint? 1. - (void)connectionDidFinishLoading:(NSURLConnection *)connection   2. {   3.         NSString *jsonString = [[NSString alloc] initWithData:self.amutabledata encoding:NSUTF8StringEncoding];   4.         NSDictionary * jsonDic = [jsonString JSONValue];    5.         NSArray * jsonarr = [jsonDic objectForKey:@"Placemark"];   6.          7.         NSDictionary *dic2 = [jsonarr objectAtIndex:0];   8.         NSString *name1 = [dic2 objectForKey:@"address"];   9. }   - (void)connectionDidFinishLoading:(NSURLConnection *)connection { NSString *jsonString = [[NSString alloc] initWithData:self.amutabledata encoding:NSUTF8StringEncoding]; NSDictionary * jsonDic = [jsonString JSONValue]; NSArray * jsonarr = [jsonDic objectForKey:@"Placemark"]; NSDictionary *dic2 = [jsonarr objectAtIndex:0]; NSString *name1 = [dic2 objectForKey:@"address"]; } 这边提下,googlemap服务请求可以以xml协议格式,也可以json协议格式。因为这边我用了json的,然后对于json的解析处理类用了SBJSON包。 具体你要解析出的内容你可以先在先将内容打印出来或是在浏览器请求后看下然后选择性解析。 然后是昨天在翻开发秘籍那本书,看到了关于这块的内容:逆向地理编码。 其实还是基于googlemap服务,只是IOS提供了一个简化的API,可供调用。 MKReverseGeocoder和他的一个代理类。原理基本和上面是一模一样。大家直接用下这两个类就明白了。 但是在ios5.0以上发现这几个类又被将之遗弃被新的CLGeocoder类代替并且去掉了代理类这一步。 [cpp] view plaincopyprint? 1. [CLGeocoder alloc] reverseGeocodeLocation:(CLLocation *) completionHandler:^(NSArray *placemarks, NSError *error)completionHandler   [CLGeocoder alloc] reverseGeocodeLocation:(CLLocation *) completionHandler:^(NSArray *placemarks, NSError *error)completionHandler } 第一个参数我们都懂,第二个参数是个block对象,至于什么是block,详情就查看文档。 现在我们回到这段内容的最开始,即在一个视图上显示。 [cpp] view plaincopyprint? 1. MKCoordinateSpan span;   2.    span.latitudeDelta = 0.05;   3.    span.longitudeDelta = 0.05;   4.    //设置可调跨度,偏移量,越小越精确    5.       6.    MKCoordinateRegion region ={self.coordinate,span};   7.    //确定一个屏幕坐标    8.    9.    [self.mapKit setRegion:region];   10.    self.mapKit.showsUserLocation = YES;//当前位置显示小蓝点   MKCoordinateSpan span; span.latitudeDelta = 0.05; span.longitudeDelta = 0.05; //设置可调跨度,偏移量,越小越精确 MKCoordinateRegion region ={self.coordinate,span}; //确定一个屏幕坐标 [self.mapKit setRegion:region]; self.mapKit.showsUserLocation = YES;//当前位置显示小蓝点 在mapView显示的位置点是在视图的center点,确定这个点需要的两个参数,一个是经纬度,一个是跨度,其实说白越小越精确,越精确就是把视图放大放大~ 反正还有很多细节的参数,在真正需要去设计这样一个应用时,再去慢慢调试。 最后我们在看下如何在地图上创建一个大头针。 先看下效果图: 这就是一般说的注解,自定义一个大头针,实现一个MKAnnotation协议。 [cpp] view plaincopyprint? 1. //    2. //  MyPin.h    3. //  MapKitTest    4. //    5. //  Created by Nono on 12-5-17.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import     10. #import     11. @interface MyPin : NSObject   12.    13. - (id)initWithCoordinate2D:(CLLocationCoordinate2D)dinate    14.                     tittle:(NSString*)title subtitle:(NSString*)subtitle;   15.    16. @end   // // MyPin.h // MapKitTest // // Created by Nono on 12-5-17. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import #import @interface MyPin : NSObject - (id)initWithCoordinate2D:(CLLocationCoordinate2D)dinate tittle:(NSString*)title subtitle:(NSString*)subtitle; @end [cpp] view plaincopyprint? 1. //    2. //  MyPin.m    3. //  MapKitTest    4. //    5. //  Created by Nono on 12-5-17.    6. //  Copyright (c) 2012年 NonoWithLilith. All rights reserved.    7. //    8.    9. #import "MyPin.h"    10.    11.    12. @implementation MyPin   13. @synthesize coordinate;   14. @synthesize title = _title;   15. @synthesize subtitle = _subtitle;   16. - (id)initWithCoordinate2D:(CLLocationCoordinate2D)dinate    17.                     tittle:(NSString*)title subtitle:(NSString*)subtitle   18. {   19.     if(self = [super init])   20.     {   21.         _title = title;   22.         _subtitle=subtitle;   23.         coordinate = dinate;   24.     }   25.     return self;   26. }   27.    28. - (void)dealloc   29. {   30.     [self.title release];   31.     [self.subtitle release];   32.     [super dealloc];   33. }   34. @end   // // MyPin.m // MapKitTest // // Created by Nono on 12-5-17. // Copyright (c) 2012年 NonoWithLilith. All rights reserved. // #import "MyPin.h" @implementation MyPin @synthesize coordinate; @synthesize title = _title; @synthesize subtitle = _subtitle; - (id)initWithCoordinate2D:(CLLocationCoordinate2D)dinate tittle:(NSString*)title subtitle:(NSString*)subtitle { if(self = [super init]) { _title = title; _subtitle=subtitle; coordinate = dinate; } return self; } - (void)dealloc { [self.title release]; [self.subtitle release]; [super dealloc]; } @end [cpp] view plaincopyprint? 1. CLLocationCoordinate2D anndiante;   2.    //为了显示比较清晰不和定位点重叠    3.    anndiante.latitude = self.coordinate.latitude + 0.0011;   4.    anndiante.longitude = self.coordinate.longitude + 0.0012;   5.    MyPin *pin = [[MyPin alloc] initWithCoordinate2D:anndiante tittle:@"测试title" subtitle:@"测试子title"];   6.    [self.mapKit addAnnotation:pin];   7.    [pin release];   CLLocationCoordinate2D anndiante; //为了显示比较清晰不和定位点重叠 anndiante.latitude = self.coordinate.latitude + 0.0011; anndiante.longitude = self.coordinate.longitude + 0.0012; MyPin *pin = [[MyPin alloc] initWithCoordinate2D:anndiante tittle:@"测试title" subtitle:@"测试子title"]; [self.mapKit addAnnotation:pin]; [pin release]; 当然对于跳出视图你可以做更多的添加以及视图自定义。 针对于Core Location和MapKit的编程基础就是这些。因为其实我的下一个项目中并不需要用到,也不做太对深入, 其实开发秘籍这本书上的细节对这块描述还有很多。看来这本熟当做以后的参考书还是不错的。 IOS学习十三:代码管理中Versions使用 分类: 移动开发_IOS学习 2012-06-03 09:26 485人阅读 评论(2) 收藏 举报 这个礼拜有点浑浑噩噩,Android那边有需求和设计要讨论和舍取。 iPhone开发这边6月马上要进入真实编码阶段。 然后除了简单设计下整体项目流程和框架,项目资源需求,包名规划(这个真心想吐槽下,大侠们有什么好点的分包命名习惯么, 以Java中思路基本不太可行,按视图,逻辑,数据这样分也不太好看。) 最重要的是搭建代码管理环境。 被Xcode4.3.2自带的的管理工具郁闷了1-2天。 有时觉得在开发中有个领进门的师傅是多门重要。 首先了解下一般版本控制工具。 早期的Xcode中自带一个SCM工具,一般会用这个来做代码管理。 那些我都没接触过,4.3.2版本中没了那个工具。 但是Xcode本身是有个repositories选项。工作副本和库的概念。 代码管理工具一般分两类git和svn。据说这两个工具mac是上都自带了。 但是我的早前自己装过git,不知道所谓的自带~~反正去终端敲几下就知道是否安装了。 这边我简单说下使用SVN来做的代码控制,因为公司提供的服务端是SVN类型的。 有钱的同志们可以去考虑GitHug收费版本,可以创建私有库。 对于Xcode上的repositories使用,我不知道是本身软件bug还是什么,反正各种奇怪问题。 一会是checkout下来的文件,显示时有两个,一个是红色的 一会提交是提示 :The operation could not be performed because the repository "MapKitTest" could not be reached. 可是明明显示和服务端是绿色状态,连接正常的。 然后把Xcode重启后,有时又能提交了。 来来回回的几个机子测试了好多回, 最后是请教了下论坛里的人,说用Versions. 好吧,下面简单说下Version这个版本控制工具。 破解版下载,我是一朋友传给我的,网上上次搜到过,不过不知道为什么,那网站今天打不开了~~(搜一下应该挺多的) 安装完以后,图标好萌, 最近发现mac上软件图标都是挺萌的。        (小人是githug,莲花状的就是Versions)。 打开软件后,我们先做最简单,就是连接公司的svn服务器,然后checkout一些项目。 add一个库。 两个地址就是公司的svn地址。粘贴完后,输入用户民密码,上面那个会多一个“用户民@”。点击就创建了。 然后选怎服务端上项目 ,checkout下来。 其他操作基本和在所有的版本控制工具一样,有代码对比,更新,提交等等。但是我特么暂时没发现冲突这概念的一些操作。 以上是从服务端checkout项目到本地然后操作。 那么一般来说,我一个新项目,要传到svn上去。 因为界面上没有直接这个标签,右键了才发现。 但是这样又会和我们在Eclipse上一些操作习惯不同, 在Android开发或者说是Eclipse上svn操作,我们直接可以share一个项目上去,然后就感觉插件直接操作了服务端项目创建,我的工作副本和svn项目的链接,然后直接初始化导入下就ok了。 而在Version中,你所谓的Import,纯粹是导入。你本地这个项目还是没有加入版本控制的。 那么你就需要重新checkout下来,才真正建立链接。 versions中还有一个add working copy这个选项。 这个不知道干嘛用,发现就是在本地添加了一个工作副本,然后做本地的代码控制(本地个人开发,代码管理~~)。 以上就是该软件的简单的使用。 但是使用中还是会出现一个恼人的bug。 我新建的类,提交上去后,同事update下来,在xcode中文件显示找不到,但是finder打开,文件是纯在了, 因此,每次都是xocde中手动删除那些找不到的文件,在add进去这些文件。 郁闷 的是,反过来,我却没有这个情况,苦逼了他了~ 问了几个人,说确实存在这个情况,暂时不知道原因~。 写本章的初衷时,给那些像我一样的新手,在身边没有老手指导,可以不用浪费那么多时间在一个svn的搭建上。 公司有老手带的人,是多幸福~ IOS学习十四:网络之ASIHttpRequest和SBJson简单使用 分类: 移动开发_IOS学习 2012-06-11 10:37 419人阅读 评论(1) 收藏 举报 现在的学习基本脱离了那几本教程, 上个礼拜正式着手代码编写。 同事UI弄得比较快,于是我只好写写网络通信,数据源模型设计以及加解密。 这边简单的说下常用的第三方网络库以及,以及json数据协议格式的简单使用。 先引入目前网上点击率最高的关于这个使用的文章(源文不详,呵呵) ASIHTTPRequest类库简介和使用说明 我只是简单说下一般项目中会用到的最基础一部分,有的东西都是用着用着就熟了,犯不着一开始记住那么多,然后没有实践都会慢慢忘掉, 我比较喜欢先简单看下,在头脑中形成一个类似于一个索引目录,不知道细节没关系,我们有了索引就可以去查阅资料嘛。 先准备下ASIHttpRequest的一些下载和添加。 1.下载地址,我是在github上下的,地址https://github.com/pokeb/asi-http-request/ 2.然后吧源文件拖进去项目,添加:CFNetwork.framework,.framework, MobileCoreServices.framework,CoreGraphics.framework和libz.1.2.3.dylib。上面文章都有介绍。 然后我们简单看下一个最简单的异步请求。 包含一个url地址,一个request,一个delegate。 [cpp] view plaincopyprint? 1. @implementation NLNetHelper   2.    3. + (void)startRequesWithContent:(NSObject *)model delegte :delegte   4. {   5.     //step 1: 根据code判断是佛要3des加密    6.     NSString *code = [model getMethidCode];   7.     NSLog(@"code是!!!!!!%@",code);   8.     if (code == @"10000") {   9.            10.     }   11.        12.     //step 2:head和body组装成jsonString    13.     NLHead *head = [[NLHead alloc] init];   14.    // head     15.        16.   //  NSString *urlString = [NSString stringWithFormat:@"%@%@.do",baseURL,code];    17.     NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"];   18.     ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url];   19.     [request setPostBody:nil];   20.     [request setDelegate:delegte];   21.     [request startAsynchronous];   22.    23.         //step1. 模型解析    24. }   @implementation NLNetHelper + (void)startRequesWithContent:(NSObject *)model delegte :delegte { //step 1: 根据code判断是佛要3des加密 NSString *code = [model getMethidCode]; NSLog(@"code是!!!!!!%@",code); if (code == @"10000") { } //step 2:head和body组装成jsonString NLHead *head = [[NLHead alloc] init]; // head // NSString *urlString = [NSString stringWithFormat:@"%@%@.do",baseURL,code]; NSURL *url = [NSURL URLWithString:@"http://www.baidu.com"]; ASIHTTPRequest *request = [ASIHTTPRequest requestWithURL:url]; [request setPostBody:nil]; [request setDelegate:delegte]; [request startAsynchronous]; //step1. 模型解析 } 代码直接项目中测试类拷贝的,主要看下面的4-5句。 因为在Android编写习惯性会把我们自己的网络处理类封装在一起。 但是ios中看了很多demo,发现请求参数处理以及request以及response返回的处理都在ViewController中处理~ 一眼看上去是方便多了,不用定义一些类似于bean类型的类来管理我们要设置进去一些属性值,用于最后转化成请求参数在网络层处理, 而是很直接的手动拼装起来。 因为这第一个项目,也不知道ios有木有这样的习惯,就是ViewController类中基本处理了当前页面的所有逻辑操作~因为看过一个我们外包版本的项目 一个ViewController代码2,3千行~~ 好了,我的意思是有需要的可以自己书写一个netManager,parseHelper等等的类。 在Android中异步的操作一般子线程然后handler来处理。 ios暂时没接触多线程这块。异步的请求,对于返回以及何时返回,返回错误,用了代理这方法。 因为我们都知道异步的这个概念,直白点就是,MainThread新起一个SubThread,子线程处理完东西后,一是用所谓的Handler神马的机制来通知主线程, 或者是经典的的回调函数嘛。而代理类,协议啊接口,正式有部分这样的性质不是么? [cpp] view plaincopyprint? 1. @optional   2.    3. // These are the default delegate methods for request status    4. // You can use different ones by setting didStartSelector / didFinishSelector / didFailSelector    5. - (void)requestStarted:(ASIHTTPRequest *)request;   6. - (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders;   7. - (void)request:(ASIHTTPRequest *)request willRedirectToURL:(NSURL *)newURL;   8. - (void)requestFinished:(ASIHTTPRequest *)request;   9. - (void)requestFailed:(ASIHTTPRequest *)request;   10. - (void)requestRedirected:(ASIHTTPRequest *)request;   11.    12. // When a delegate implements this method, it is expected to process all incoming data itself    13. // This means that responseData / responseString / downloadDestinationPath etc are ignored    14. // You can have the request call a different method by setting didReceiveDataSelector    15. - (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data;   16.    17. // If a delegate implements one of these, it will be asked to supply credentials when none are available    18. // The delegate can then either restart the request ([request retryUsingSuppliedCredentials]) once credentials have been set    19. // or cancel it ([request cancelAuthentication])    20. - (void)authenticationNeededForRequest:(ASIHTTPRequest *)request;   21. - (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request;   @optional // These are the default delegate methods for request status // You can use different ones by setting didStartSelector / didFinishSelector / didFailSelector - (void)requestStarted:(ASIHTTPRequest *)request; - (void)request:(ASIHTTPRequest *)request didReceiveResponseHeaders:(NSDictionary *)responseHeaders; - (void)request:(ASIHTTPRequest *)request willRedirectToURL:(NSURL *)newURL; - (void)requestFinished:(ASIHTTPRequest *)request; - (void)requestFailed:(ASIHTTPRequest *)request; - (void)requestRedirected:(ASIHTTPRequest *)request; // When a delegate implements this method, it is expected to process all incoming data itself // This means that responseData / responseString / downloadDestinationPath etc are ignored // You can have the request call a different method by setting didReceiveDataSelector - (void)request:(ASIHTTPRequest *)request didReceiveData:(NSData *)data; // If a delegate implements one of these, it will be asked to supply credentials when none are available // The delegate can then either restart the request ([request retryUsingSuppliedCredentials]) once credentials have been set // or cancel it ([request cancelAuthentication]) - (void)authenticationNeededForRequest:(ASIHTTPRequest *)request; - (void)proxyAuthenticationNeededForRequest:(ASIHTTPRequest *)request; 以上就是所有的可选的带了方法,看意思就明白。 好了,以上只是ASIHttpRequest中部分的功能,基本就能解决我们一般网络类应用中大部分的功能了吧。 二:SBJson使用 虽然现在看到说sdk5.0以上,已经集成了json解析库。同时貌似说性能还高,但是,可能我们的现在的应用还要兼容下5.0以下的版本。 反正这些都是需要我们客观看待然后主观舍取。 SBJSon同样的一个第三方包 1.下载地址 https://github.com/stig/json-framework 我们都知道,json的格式就是key value。 说白了json格式就是一种带着特性的String字窜。 我们把我们要的数据组装成这样的字窜床底给服务端,然后服务端返回同样这样字窜的数据,我们要解析然后提取出内容来。 看过java我们都知道,其实里面是map的遍历。 同样的,在ios,我们需要先定义一个字典,然后把需要传递的数据以键值对存入,然后调用json解析器生成jsonString。 同样,也会有个反序列化咯。 [dictionary JSONRepresentation]; 字典生成jsonString。  NSMutableDictionary *dic = [jsonString JSONValue]; jsonString转化成字典 其实相对于ios上的,java中其实封装的更加完美。能直接操作javabean-》jsonString。 因为用了反射,后来查了下,貌似ios也是有反射这内容啊~ 为什么说bean—>jsonString呢。 因为,大部分,比如我们一个用户登陆通信,我们会设计一个LoginBean,包含两个字段 username和password,然后是setter,getter方法。 当然,不用bean,直接在ViewCotroller中把name啊password设置如dic中,因为我看了几个demo版本都这样~,甚至我们外包的那个项目也是这么搞。 好了,反正简单来说。 数据转化,如果使用了类似于bean的自定义类,那么bean—》dic—>jsonString。反解析时同样。 因此我的处理是: [cpp] view plaincopyprint? 1. -(NSString *)bean2jsonString{   2.     NSMutableDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys:   3.              partnerCode, @"partnerCode",   4.              version, @"version",   5.              prov,@"prov",   6.              mobile,@"moblie",   7.              methodId,@"methodId",   8.              userId,@"useId",   9.              [NSDictionary dictionaryWithObjectsAndKeys:postTime, @"postTime",md5Sign,@"md5Sign",nil],@"other",   10.             nil];   11.     return [dictionary JSONRepresentation];   12. }   13.    14. - (void)jsonString2Bean:(NSString *)jsonString   15. {   16.     NSMutableDictionary *dic = [jsonString JSONValue];   17.     NSString *partnerCodeString = [NSString stringWithFormat:@"修改过的%@",[dic objectForKey:@"partnerCode"]];   18.     [self setPartnerCode:partnerCodeString];   19.     }   -(NSString *)bean2jsonString{ NSMutableDictionary *dictionary = [NSDictionary dictionaryWithObjectsAndKeys: partnerCode, @"partnerCode", version, @"version", prov,@"prov", mobile,@"moblie", methodId,@"methodId", userId,@"useId", [NSDictionary dictionaryWithObjectsAndKeys:postTime, @"postTime",md5Sign,@"md5Sign",nil],@"other", nil]; return [dictionary JSONRepresentation]; } - (void)jsonString2Bean:(NSString *)jsonString { NSMutableDictionary *dic = [jsonString JSONValue]; NSString *partnerCodeString = [NSString stringWithFormat:@"修改过的%@",[dic objectForKey:@"partnerCode"]]; [self setPartnerCode:partnerCodeString]; } 该方法是在bean中。反正觉得没有Android中json用起来方便,你扔个标准bean对象,就给你出来一个jsonString。 其实也是很简单的两块内容,刚做了,记录下。下面准备调通下加密这块,分享和借鉴 IOS学习十五:通信加密 分类: 移动开发_IOS学习 2012-06-29 13:25 625人阅读 评论(0) 收藏 举报 通信加解密基本算是每个涉及到用户信息的客户端都会用到的一个技术。 一般我们可能就做简单的防篡改和密文加密。 很多时候做一个加密只不过是一个小小的心理安慰吧了,因为纯粹的从安全角度来说,安全性真的不高。 对于一些手机支付以及银联的客户端,我看到有用的证书什么来实现。 因为没做过,所以也不是太了解。 这边就说下最简单的加密方案。 一:MD5数字摘要。 准确来说,MD5不能叫做加解密,因为它不可逆性。 一般我们理解的加解密是能加密,然后解密的。 MD5只是根据数据生个一个校验码,然后对于数据接受者接受到内容后同样的在通过md5来生成校验码于之前的校验码对比是否一致, 从而来判断数据在传送过程中是否被截取篡改过。 说白了,其实在传输过程中,仅仅md5技术,数据任然是明文的。 下面我来来看下IOS中对md5加密的支持。 [cpp] view plaincopyprint? 1. const char *original_str = [string UTF8String];//string为摘要内容,转成char    2.    3.  /****系统api~~~~*****/   4.    unsigned char result[CC_MD5_DIGEST_LENGTH];     5.    CC_MD5(original_str, strlen(original_str), result);//调通系统md5加密    6.    NSMutableString *hash = [[NSMutableString string]autorelease];   7.    for (int i = 0; i < 16; i++)   8.        [hash appendFormat:@"%02X", result[i]];   9.       return hash ;//校验码   const char *original_str = [string UTF8String];//string为摘要内容,转成char /****系统api~~~~*****/ unsigned char result[CC_MD5_DIGEST_LENGTH]; CC_MD5(original_str, strlen(original_str), result);//调通系统md5加密 NSMutableString *hash = [[NSMutableString string]autorelease]; for (int i = 0; i < 16; i++) [hash appendFormat:@"%02X", result[i]]; return hash ;//校验码 代码很简单,因为内部算法都是系统已经完成的。 对于以上来看,仍然没有很好的处理密文传输只是在数据传输过程成做了一个简单的防篡改。 因此需要使用一种能生成密文的安全机制类支持。 二:ios中3DES加密 3DES是一种对称的加密方式,因为用的同一个密钥。 对于加解密的安全性什么大家可以google,baidu自己找资料参考。 我也不过是简单的说一下通信加密中的一种可实现方案而已。 同样的3DES加密基本也都是统一的,系统也直接提供了API,基本代码如下 [cpp] view plaincopyprint? 1. //3des加解密    2. + (NSString*)TripleDES:(NSString*)plainText encryptOrDecrypt:(CCOperation)encryptOrDecrypt   3. {   4.        5.     const void *vplainText;   6.     size_t plainTextBufferSize;   7.        8.     if (encryptOrDecrypt == kCCDecrypt)//解密    9.     {   10.         NSData *EncryptData = [GTMBase64 decodeData:[plainText dataUsingEncoding:NSUTF8StringEncoding]];   11.         plainTextBufferSize = [EncryptData length];   12.         vplainText = [EncryptData bytes];   13.     }   14.     else //加密    15.     {   16.         NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding];   17.         plainTextBufferSize = [data length];   18.         vplainText = (const void *)[data bytes];   19.     }   20.        21.     CCCryptorStatus ccStatus;   22.     uint8_t *bufferPtr = NULL;   23.     size_t bufferPtrSize = 0;   24.     size_t movedBytes = 0;   25.        26.     bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1);   27.     bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t));   28.     memset((void *)bufferPtr, 0x0, bufferPtrSize);   29.     // memset((void *) iv, 0x0, (size_t) sizeof(iv));    30.        31.      const void *vkey = (const void *) [DESKEY UTF8String];   32.    // NSString *initVec = @"init Vec";    33.     //const void *vinitVec = (const void *) [initVec UTF8String];    34.    //  Byte iv[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF};    35.     ccStatus = CCCrypt(encryptOrDecrypt,   36.                        kCCAlgorithm3DES,   37.                         kCCOptionPKCS7Padding | kCCOptionECBMode,   38.                        vkey,    39.                        kCCKeySize3DES,   40.                        nil,    41.                        vplainText,   42.                        plainTextBufferSize,   43.                        (void *)bufferPtr,   44.                        bufferPtrSize,   45.                        &movedBytes);   46.     //if (ccStatus == kCCSuccess) NSLog(@"SUCCESS");    47.     /*else if (ccStatus == kCC ParamError) return @"PARAM ERROR";  48.      else if (ccStatus == kCCBufferTooSmall) return @"BUFFER TOO SMALL";  49.      else if (ccStatus == kCCMemoryFailure) return @"MEMORY FAILURE";  50.      else if (ccStatus == kCCAlignmentError) return @"ALIGNMENT";  51.      else if (ccStatus == kCCDecodeError) return @"DECODE ERROR";  52.      else if (ccStatus == kCCUnimplemented) return @"UNIMPLEMENTED"; */   53.        54.     NSString *result;   55.        56.     if (encryptOrDecrypt == kCCDecrypt)   57.     {   58.         result = [[[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr    59.                                                                 length:(NSUInteger)movedBytes]    60.                                         encoding:NSUTF8StringEncoding]    61.                   autorelease];   62.     }   63.     else   64.     {   65.         NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes];   66.         result = [GTMBase64 stringByEncodingData:myData];   67.     }   68.        69.     return result;   //3des加解密 + (NSString*)TripleDES:(NSString*)plainText encryptOrDecrypt:(CCOperation)encryptOrDecrypt { const void *vplainText; size_t plainTextBufferSize; if (encryptOrDecrypt == kCCDecrypt)//解密 { NSData *EncryptData = [GTMBase64 decodeData:[plainText dataUsingEncoding:NSUTF8StringEncoding]]; plainTextBufferSize = [EncryptData length]; vplainText = [EncryptData bytes]; } else //加密 { NSData* data = [plainText dataUsingEncoding:NSUTF8StringEncoding]; plainTextBufferSize = [data length]; vplainText = (const void *)[data bytes]; } CCCryptorStatus ccStatus; uint8_t *bufferPtr = NULL; size_t bufferPtrSize = 0; size_t movedBytes = 0; bufferPtrSize = (plainTextBufferSize + kCCBlockSize3DES) & ~(kCCBlockSize3DES - 1); bufferPtr = malloc( bufferPtrSize * sizeof(uint8_t)); memset((void *)bufferPtr, 0x0, bufferPtrSize); // memset((void *) iv, 0x0, (size_t) sizeof(iv)); const void *vkey = (const void *) [DESKEY UTF8String]; // NSString *initVec = @"init Vec"; //const void *vinitVec = (const void *) [initVec UTF8String]; // Byte iv[] = {0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF}; ccStatus = CCCrypt(encryptOrDecrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding | kCCOptionECBMode, vkey, kCCKeySize3DES, nil, vplainText, plainTextBufferSize, (void *)bufferPtr, bufferPtrSize, &movedBytes); //if (ccStatus == kCCSuccess) NSLog(@"SUCCESS"); /*else if (ccStatus == kCC ParamError) return @"PARAM ERROR"; else if (ccStatus == kCCBufferTooSmall) return @"BUFFER TOO SMALL"; else if (ccStatus == kCCMemoryFailure) return @"MEMORY FAILURE"; else if (ccStatus == kCCAlignmentError) return @"ALIGNMENT"; else if (ccStatus == kCCDecodeError) return @"DECODE ERROR"; else if (ccStatus == kCCUnimplemented) return @"UNIMPLEMENTED"; */ NSString *result; if (encryptOrDecrypt == kCCDecrypt) { result = [[[NSString alloc] initWithData:[NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes] encoding:NSUTF8StringEncoding] autorelease]; } else { NSData *myData = [NSData dataWithBytes:(const void *)bufferPtr length:(NSUInteger)movedBytes]; result = [GTMBase64 stringByEncodingData:myData]; } return result; 这个在网上也能搜索到详细代码。 但是要注意到一点: [cpp] view plaincopyprint? 1. CCCrypt(encryptOrDecrypt,   2.                        kCCAlgorithm3DES,   3.                         kCCOptionPKCS7Padding | kCCOptionECBMode,   4.                        vkey,    5.                        kCCKeySize3DES,   6.                        nil,    7.                        vplainText,   8.                        plainTextBufferSize,   9.                        (void *)bufferPtr,   10.                        bufferPtrSize,   11.                        &movedBytes);   CCCrypt(encryptOrDecrypt, kCCAlgorithm3DES, kCCOptionPKCS7Padding | kCCOptionECBMode, vkey, kCCKeySize3DES, nil, vplainText, plainTextBufferSize, (void *)bufferPtr, bufferPtrSize, &movedBytes); 这个里面的参数可能会根据你服务端使用的对应的3des算法构造时参数的不同而需要自己调整。 比如我在网上看到的这个第三个参数只是用了kCCOptionPKCS7Padding,第六个可选参数用了上面一个自定义的iv。 但是这边根据服务器,这个参数是nil才对应。 这边也附上java端的加解密代码 [java] view plaincopyprint? 1. public String encryptThreeDESECB(String src,String key) throws Exception   2.     {   3.       DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));   4.       SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");   5.       SecretKey securekey = keyFactory.generateSecret(dks);   6.          7.       Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");   8.       cipher.init(Cipher.ENCRYPT_MODE, securekey);   9.       byte[] b=cipher.doFinal(src.getBytes());   10.          11.       BASE64Encoder encoder = new BASE64Encoder();   12.       return encoder.encode(b).replaceAll("\r", "").replaceAll("\n", "");   13.          14.     }   15.    16.     //3DESECB解密,key必须是长度大于等于 3*8 = 24 位    17.     public String decryptThreeDESECB(String src,String key) throws Exception   18.     {   19.       //--通过base64,将字符串转成byte数组    20.       BASE64Decoder decoder = new BASE64Decoder();   21.       byte[] bytesrc = decoder.decodeBuffer(src);   22.       //--解密的key    23.       DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8"));   24.       SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede");   25.       SecretKey securekey = keyFactory.generateSecret(dks);   26.          27.       //--Chipher对象解密    28.       Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding");     29.       cipher.init(Cipher.DECRYPT_MODE, securekey);     30.       byte[] retByte = cipher.doFinal(bytesrc);     31.                32.       return new String(retByte);   33.     }   public String encryptThreeDESECB(String src,String key) throws Exception { DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8")); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede"); SecretKey securekey = keyFactory.generateSecret(dks); Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); cipher.init(Cipher.ENCRYPT_MODE, securekey); byte[] b=cipher.doFinal(src.getBytes()); BASE64Encoder encoder = new BASE64Encoder(); return encoder.encode(b).replaceAll("\r", "").replaceAll("\n", ""); } //3DESECB解密,key必须是长度大于等于 3*8 = 24 位 public String decryptThreeDESECB(String src,String key) throws Exception { //--通过base64,将字符串转成byte数组 BASE64Decoder decoder = new BASE64Decoder(); byte[] bytesrc = decoder.decodeBuffer(src); //--解密的key DESedeKeySpec dks = new DESedeKeySpec(key.getBytes("UTF-8")); SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DESede"); SecretKey securekey = keyFactory.generateSecret(dks); //--Chipher对象解密 Cipher cipher = Cipher.getInstance("DESede/ECB/PKCS5Padding"); cipher.init(Cipher.DECRYPT_MODE, securekey); byte[] retByte = cipher.doFinal(bytesrc); return new String(retByte); } 内容也很少,这这么点。 然后是key,也就是共用密钥的客户端和服务端都保存一个。 简单从数据传输来说,密文传输了,安全性相对来说提高了不少。 但是如果破解了客户端代码,那么其实密钥也就暴露了。 这对于android上面来说,因为反编译额纯在,安全性不敢恭维, ios的貌似好一点,因为暂未听说反编译ios的app的。 以上就是一种简单的通信加密方案。 当然,其实这些其实算是通用技术~ IOS学习之十六:网络数据的XML解析 分类: 移动开发_IOS学习 2012-08-04 11:32 827人阅读 评论(3) 收藏 举报 网络应用中的数据解析,因为最近的应用,无论是Android的和ios平台的,一直用也是建议用的都是Json解析, xml解析都有点被遗忘了。 然后最近自己在做着玩一个ios的小应用,涉及网络数据的抓取,一些网站可能都提供了自己api平台,这些一般都是支持 我们对于数据协议格式的设定的。但是后来我在找寻到一些Rss资源时,发现返回的数据都是xml格式的, 因此,那就只好用xml解析了。 XML解析其实这个概念出现了算够久了,以前javaweb什么到处都在用。这边我们主要大致介绍下,然后在在ios编程如何使用。 XML解析一般分两种模式SAX和DOM,事件和文档。具体解析google去吧,有详细。不过看了下面的两个例子,一般就了解了。 一:XML解析之SAX解析,以及对NSXMLParser的应用。 sax解析说白了,就是一个事物模型解析,从头开始读取文档然后根据读取到的头标签标签时要怎么处理,读完头标签后,理论上是读取标签值了, 然后读取后遇到结束标签等 简单举个例子 头标签,里面的xmlns,可以看成是属性 呵呵呵呵结束标签,中间的“呵呵呵呵”是首尾标签标签值空间 ....... 好了,那么在ios开发中如何使用。 SDK本身是提供了NSXMLParser解析器。 [cpp] view plaincopyprint? 1. -(BOOL)parser:(NSString*)string   2. {   3.     //系统自带的    4.         NSXMLParser *par = [[[NSXMLParser alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]]autorelease];   5.         [par setDelegate:self];//设置NSXMLParser对象的解析方法代理      6.         return [par parse];//调用代理解析NSXMLParser对象,看解析是否成功   }    7.    8. }   9.    10. #pragma mark xmlparser    11. //step 1 :准备解析    12. - (void)parserDidStartDocument:(NSXMLParser *)parser   13. {   14. //    NSLog(@"%@",NSStringFromSelector(_cmd) );    15.     16. }   17. //step 2:准备解析节点    18. - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict   19. {   20. //    NSLog(@"%@",NSStringFromSelector(_cmd) );    21. }   22. //step 3:获取首尾节点间内容    23. - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string   24. {   25.     NSLog(@"%@",NSStringFromSelector(_cmd) );   26. }   27.    28. //step 4 :解析完当前节点    29. - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName   30. {   31.    NSLog(@"%@",NSStringFromSelector(_cmd) );   32. }   33.    34. //step 5;解析结束    35. - (void)parserDidEndDocument:(NSXMLParser *)parser   36. {   37. //    NSLog(@"%@",NSStringFromSelector(_cmd) );    38. }   39. //获取cdata块数据    40. - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock   41. {   42. //    NSLog(@"%@",NSStringFromSelector(_cmd) );    43. }   -(BOOL)parser:(NSString*)string { //系统自带的 NSXMLParser *par = [[[NSXMLParser alloc] initWithData:[string dataUsingEncoding:NSUTF8StringEncoding]]autorelease]; [par setDelegate:self];//设置NSXMLParser对象的解析方法代理 return [par parse];//调用代理解析NSXMLParser对象,看解析是否成功 } } #pragma mark xmlparser //step 1 :准备解析 - (void)parserDidStartDocument:(NSXMLParser *)parser { // NSLog(@"%@",NSStringFromSelector(_cmd) ); } //step 2:准备解析节点 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { // NSLog(@"%@",NSStringFromSelector(_cmd) ); } //step 3:获取首尾节点间内容 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { NSLog(@"%@",NSStringFromSelector(_cmd) ); } //step 4 :解析完当前节点 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { NSLog(@"%@",NSStringFromSelector(_cmd) ); } //step 5;解析结束 - (void)parserDidEndDocument:(NSXMLParser *)parser { // NSLog(@"%@",NSStringFromSelector(_cmd) ); } //获取cdata块数据 - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock { // NSLog(@"%@",NSStringFromSelector(_cmd) ); } 1.初始化解析器,传入你要解析的数据。 2.parse,启动解析,返回一个是否解析成功Bool值。 3.基本你要处理的就在下面实现的1-5个代理方法了。 其实代理方法和详细,就是一个事物进行流程: step1是准备解析,然后没意外就是执行到了——> step2读取到第一个头节点了,然后如果内部有属性值,你可以获取出来,读完头节点,我们会进去值域——》 step3对于简单的节点,可能直接就是一个string值了,但是看例子我们会知道,很多情况下,该节点的值域包含的于是一个节点——》 这步其实分两种,如果是值,那么就是执行step4,获取值的字窜,如果是子节点呢,我们一看就知道,它又是进行了step2, 即读取到头标签了,其实你是很人读一片文章流程一样,只不过我们脑中有个印象是头标签了,我们要做什么,独到 头标签的最后一个符号">" 下面进去值域,独到了字窜的话就调用了foundCharacters:(NSString *)string,如果又读到这样的,那就又是头标签了。——》 step5就是读到开始尾标签符号了。 最后一个方法 foundCDATA:(NSData *)CDATABlock,其实也是一个格式 [html] view plaincopyprint? 1.    2. 减卐肥™评论: 搜索
 
评价: 力荐

  4. ]]>   5.
   减卐肥™评论: 搜索

评价: 力荐

]]>
好了,方法和流程大致了解了,拿一个我最近遇到的例子,好多时候,我们会遇到这样读取一组类似于json中数组形式的数据 [html] view plaincopyprint? 1.    2. 我是标题   3. http://write.blog.csdn.net/postedit   4. ...   5. zh-cn   6. Fri, 03 Aug 2012 06:20:31 GMT   7. ...   8. ...   9. ...   10. ...   11. ...   12. ...   13. ...   14. ...   15. ...   16. ...   17. ...   18. ...   19. ...   20. ...   21. ...   22. ...   23. ...   24. ...   25. ...   26. ...   27.    我是标题 http://write.blog.csdn.net/postedit ... zh-cn Fri, 03 Aug 2012 06:20:31 GMT ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... ... 一般来说,我们要的数据其实都是这20个item,对吧,每个item下都是相同的3个标签,title,author,time。形式上 其实一种数组形式 那么要怎么解析呢 1,首先我们可能先申明一个array数组容器用来存放这个20个对象,然后每个item对象中又有3个元素,那么我们可以 考虑用一个字典数据结构来表示每个item。 2.需要至少申请两个空间来作为类似于“哨兵”存储当前执行到的节点名,以及节点的值。 3.然后每次执行到读取到item时,初始化我们上面说道的一个字典数据结构。 4.在foundCharacters:方法中一直保存当前最新的值(当然,这里面其实会有个小瑕疵,下面会说到)。 5.在标签结束的方法,我们把标签名和值已键值对存入上面初始化的字典容器中。 [cpp] view plaincopyprint? 1. #pragma mark xmlparser    2. //step 1 :准备解析    3. - (void)parserDidStartDocument:(NSXMLParser *)parser   4. {   5. //    NSLog(@"%@",NSStringFromSelector(_cmd) );    6.        7.     parserObjects = [[NSMutableArray alloc]init];   8. }   9. //step 2:准备解析节点    10. - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict   11. {   12. //    NSLog(@"%@",NSStringFromSelector(_cmd) );    13.        14.     self.currentText = [[NSMutableString alloc]init];   15.     [currentText release];   16.     if ([elementName isEqualToString:@"item"]) {   17.         NSMutableDictionary *newNode = [[ NSMutableDictionary alloc ] initWithCapacity : 0 ];   18.         twitterDic = newNode;   19.         [parserObjects addObject :newNode];   20.         [newNode release];   21.     }   22.     else if(twitterDic) {   23.         NSMutableString *string = [[ NSMutableString alloc ] initWithCapacity : 0 ];   24.         [twitterDic setObject :string forKey :elementName];   25.         [string release ];   26.         currentElementName = elementName;   27.     }   28.    29.        30. }   31. //step 3:获取首尾节点间内容    32. - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string   33. {   34.     NSLog(@"%@",NSStringFromSelector(_cmd) );   35.     [currentText appendString:string];   36. }   37.    38. //step 4 :解析完当前节点    39. - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName   40. {   41.     if ([elementName isEqualToString:@"item"]) {   42.         twitterDic = nil;   43.     }else    44.         if ([elementName isEqualToString:currentElementName]) {   45.            46.             if ([elementName isEqualToString:@"description"]   47.                 ||[elementName isEqualToString:@"content:encoded"]) {   48.                 [twitterDic setObject:Cdata forKey:currentElementName];   49.             }else {   50.                 [twitterDic setObject:currentText forKey:currentElementName];   51.             }   52.     }   53.    54. }   55.    56. //step 5;解析结束    57. - (void)parserDidEndDocument:(NSXMLParser *)parser   58. {   59. }   60. //获取cdata块数据    61. - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock   62. {   63.    64.     Cdata =[[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding];   65. }   #pragma mark xmlparser //step 1 :准备解析 - (void)parserDidStartDocument:(NSXMLParser *)parser { // NSLog(@"%@",NSStringFromSelector(_cmd) ); parserObjects = [[NSMutableArray alloc]init]; } //step 2:准备解析节点 - (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict { // NSLog(@"%@",NSStringFromSelector(_cmd) ); self.currentText = [[NSMutableString alloc]init]; [currentText release]; if ([elementName isEqualToString:@"item"]) { NSMutableDictionary *newNode = [[ NSMutableDictionary alloc ] initWithCapacity : 0 ]; twitterDic = newNode; [parserObjects addObject :newNode]; [newNode release]; } else if(twitterDic) { NSMutableString *string = [[ NSMutableString alloc ] initWithCapacity : 0 ]; [twitterDic setObject :string forKey :elementName]; [string release ]; currentElementName = elementName; } } //step 3:获取首尾节点间内容 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string { NSLog(@"%@",NSStringFromSelector(_cmd) ); [currentText appendString:string]; } //step 4 :解析完当前节点 - (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName { if ([elementName isEqualToString:@"item"]) { twitterDic = nil; }else if ([elementName isEqualToString:currentElementName]) { if ([elementName isEqualToString:@"description"] ||[elementName isEqualToString:@"content:encoded"]) { [twitterDic setObject:Cdata forKey:currentElementName]; }else { [twitterDic setObject:currentText forKey:currentElementName]; } } } //step 5;解析结束 - (void)parserDidEndDocument:(NSXMLParser *)parser { } //获取cdata块数据 - (void)parser:(NSXMLParser *)parser foundCDATA:(NSData *)CDATABlock { Cdata =[[NSString alloc] initWithData:CDATABlock encoding:NSUTF8StringEncoding]; } 对于上面代码说几点 1.我次奥,有几处内存泄露~~~ 2.在获取值为什么不直接currentString = string 这是实践发现的问题 - (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string  注意这个代理方法的注释    // This returns the string of the characters encountered thus far. You may not necessarily get the longest character run. The parser reserves the right to hand these to the delegate as potentially many calls in a row to -parser:foundCharacters: 下面是google翻译。 这将返回迄今为止遇到的字符的字符串。你不一定得到的最长字符运行。解析器有权交行解析器可能多次呼吁这些委托:foundCharacters: 这个说明,在获取一个标签首尾间的字符数据时,这个方法可能被调用多次。 举个我碰到的最简单的列子 © 2012, douban.com. 我在解析这个节点时,上面方法就调用了两次, 第一次只返回&,紧接着第二次返回copy; 2012, douban.com. 因此你如果要获取完整的的,应该用string的append方法来获取完整的一条记录。 3.解析速度的优化,比如我们只需要item中数据,那么在独到非这个域内的标签,我们的哨兵不需要追中的保存key和value值。 因此我做了一处字典的释放和判断,在found中想减少string的赋值,当然你也可以在全局添加个标记位来控制 但是总体来说,这种优化基本微乎其微,而且造成我内存莫名其妙的泄露了~~ 4.以上思路可以参考,代码因为写的太冲忙,有写内存上的问题,就不要参考了,呵呵,过几天我子在改改, 可以做一个很好rss解析的模板。 二:Dom文档解析模型,TBXML第三方包应用。 dom解析模型就像一个树结构,节点,子节点,兄弟节点等等。 这个其实最后被我抛弃了,这个解析器太简化了,太简洁的东西导致控制的入口点太少,就比如一个一键优化的软件的概念是一样的, 一键清楚缓存,优化配置,文件归类等等。人为控制就少了,导致我解析上面那个模型时,只知道遍历存储~。但是这个解析期对部分要求不高的xml解析其实挺好分,真的很简洁。 [cpp] view plaincopyprint? 1. //- (void)recurrence:(TBXMLElement *)element {    2. //        3. //    NSString *eleName = [TBXML elementName:element];     4. //    NSString *eleText = [TBXML textForElement:element];    5. //    if ([eleName isEqualToString:@"item"]) {    6. //        self recurrence:element    7. //    }    8. //        9. //        10. //        11. //        12. //    do {    13. //            14. //        NSString *eleName = [TBXML elementName:element];     15. //        NSString *eleText = [TBXML textForElement:element];     16. //            17. //        //递归处理子树    18. //        if (element->firstChild) {    19. //            NSLog(@"<%@>:",eleName);// Display the name of the element    20. //                21. //            [self recurrence:element->firstChild];    22. //        }else {    23. //            NSLog(@"<%@>:%@",eleName,eleText);// Display the name of the element    24. //                25. //            TBXMLElement *parent = element->parentElement;    26. //            if ([[TBXML elementName:parent] isEqualToString:@"item"]) {    27. //                NLRssInfo *info = [[[NLRssInfo alloc]init] autorelease];    28. //                    29. //                if ([eleName isEqualToString:@"title"]) {    30. //                    info.title = eleText;     31. //                }    32. //                    33. //                    34. //                [dataArr addObject:info];    35. //            }    36. //                37. //        }    38. //            39. //            40. //        //迭代处理兄弟树    41. //    } while ((element = element->nextSibling));    42. //}   //- (void)recurrence:(TBXMLElement *)element { // // NSString *eleName = [TBXML elementName:element]; // NSString *eleText = [TBXML textForElement:element]; // if ([eleName isEqualToString:@"item"]) { // self recurrence:element // } // // // // // do { // // NSString *eleName = [TBXML elementName:element]; // NSString *eleText = [TBXML textForElement:element]; // // //递归处理子树 // if (element->firstChild) { // NSLog(@"<%@>:",eleName);// Display the name of the element // // [self recurrence:element->firstChild]; // }else { // NSLog(@"<%@>:%@",eleName,eleText);// Display the name of the element // // TBXMLElement *parent = element->parentElement; // if ([[TBXML elementName:parent] isEqualToString:@"item"]) { // NLRssInfo *info = [[[NLRssInfo alloc]init] autorelease]; // // if ([eleName isEqualToString:@"title"]) { // info.title = eleText; // } // // // [dataArr addObject:info]; // } // // } // // // //迭代处理兄弟树 // } while ((element = element->nextSibling)); //} 递归遍历,常规的树操作,具体内容可以网上搜搜,很多。 并且开源库的好处就是有源代码,也就3个类,6个文件,有兴趣可以研究研究,貌似大部分代码是用C写的。 IOS学习之十七:Grand Central Dispatch(GCD)编程基础 分类: 移动开发_IOS学习 2012-08-05 09:26 154人阅读 评论(0) 收藏 举报 有过编程经验的人,基本都会接触到多线程这块。 在java中以及Android开发中,大量的后台运行,异步消息队列,基本都是运用了多线程来实现。 同样在,在ios移动开发和Android基本是很类似的一种模型。 但是很多时候,在应用开发中,我们会发现本身并没有自己编码去处理一些并发的事件,去开辟新的子线程等等。 (虽然一般的调用sdk发起一个网络请求,系统都是会默认给你新起一个线程去处理的)。 整个程序看上去基本就是在Main线程中执行。 确实也是这样的一种现象,因为我们基本都是在操作控件的布局,对控件数据添加,对于UI对象的更新都是在主线程的进行。 即便等下我们看到我们开启了一个新的子线程用来获取处理数据,最后还是需要通过通知UI主线程来刷新。 当然了,ios本身也是和大部分语言一样,有NSThread线程类(我们都知道java中我们用到这个类)。 这些系统比较底层的api类,可以被我用来书写自己的并发线程和操作队列。 学过Android的我们都知道Handler,Looper这个概念,Looper说白了就是一个主线程的消息循环队列,handler一般理解就是用于子线程和UI主线程一些数据交互。 看了下ios的GCD特性,发现他们之间颇有几分相似。  1.下面来看下如何使用gcd编程的异步 [cpp] view plaincopyprint? 1.    2. dispatch_async(dispatch_get_global_queue(0, 0), ^{   3.     // 处理耗时操作的代码块...    4.        5.     //通知主线程刷新    6.     dispatch_async(dispatch_get_main_queue(), ^{   7.         //回调或者说是通知主线程刷新,    8.     });   9.        10. });   dispatch_async(dispatch_get_global_queue(0, 0), ^{ // 处理耗时操作的代码块... //通知主线程刷新 dispatch_async(dispatch_get_main_queue(), ^{ //回调或者说是通知主线程刷新, }); }); dispatch_async开启一个异步操作,第一个参数是指定一个gcd队列,第二个参数是分配一个处理事物的程序块到该队列。 dispatch_get_global_queue(0, 0),指用了全局队列。 一般来说系统本身会有3个队列。 global_queue,current_queue,以及main_queue. 获取一个全局队列是接受两个参数,第一个是我分配的事物处理程序块队列优先级。分高低和默认,0为默认2为高,-2为低 [cpp] view plaincopyprint? 1. #define DISPATCH_QUEUE_PRIORITY_HIGH     2    2. #define DISPATCH_QUEUE_PRIORITY_DEFAULT  0    3. #define DISPATCH_QUEUE_PRIORITY_LOW     (-2)   #define DISPATCH_QUEUE_PRIORITY_HIGH 2 #define DISPATCH_QUEUE_PRIORITY_DEFAULT 0 #define DISPATCH_QUEUE_PRIORITY_LOW (-2) 处理完事物后,需要将结果返回给或者是刷新UI主线程,同样,和上面一样,抓取主线程,程序块操作。 //天啊,手贱不小心点到了home间,会退后发现没保存~~~写的并发一块内容都没了!!! 二:GCD之并发概念 其实对于编程中,我们一直提及到的几个概念,同步,异步,并发,锁等。 有时觉得一下子还真说不清。 下面我们以上面提到的图片加载来看下这3个概念我的理解 1同步: [cpp] view plaincopyprint? 1. for (int i = 0 ; i < 10; i++) {   2.       3.       UIImage *img = [self getImgeWith:[urlArr objectForIndex:i]];   4.        [myImgV[i] setImage:img];   5.         6.  }   for (int i = 0 ; i < 10; i++) { UIImage *img = [self getImgeWith:[urlArr objectForIndex:i]]; [myImgV[i] setImage:img]; } 假设我要加载10个图片,我现在拥有这些图片的资源地址,保存在一个数组中。 我们先以获取第一张图片来举例: 同步执行的概念就是,我获取完第一张图片的, 执行了for循环第一句返回了img后,我才能执行第二句,UI界面的刷新。 如果第一句返回的时间需要10秒,那我程序的响应就仿佛一直卡在这里一样,我无法进行其他操作。必须等它返回!! 因此,同步的一个很好理解的感念就是,一步走到黑。 2.异步 [cpp] view plaincopyprint? 1. for (int i = 0 ; i < 10; i++) {   2.       dispatch_async(dispatch_get_global_queue(0, 0), ^{   3.       // 处理耗时操作的代码块...    4.        UIImage *img = [self getImgeWith:[urlArr objectForIndex:i]];   5.       //通知主线程刷新    6.       dispatch_async(dispatch_get_main_queue(), ^{   7.           //回调或者说是通知主线程刷新,    8.             [myImgV[i] setImage:img];   9.       });   10.          11.   });   for (int i = 0 ; i < 10; i++) { dispatch_async(dispatch_get_global_queue(0, 0), ^{ // 处理耗时操作的代码块... UIImage *img = [self getImgeWith:[urlArr objectForIndex:i]]; //通知主线程刷新 dispatch_async(dispatch_get_main_queue(), ^{ //回调或者说是通知主线程刷新, [myImgV[i] setImage:img]; }); }); 看了这代码,我们会说,异步操作那个假设还是要10秒啊,总体看来,执行一张图片的时间加载还是要在10秒左右啊, 貌似异步没什么鸟用么。但是,别忽略了其中一点,也黑丝核心的一点,此时我们图片获取操作放在里一个线程队列里, 此刻,虽然我们看着图片的加载还是需要10秒才会出来,但是,在这10秒期间,我们的UI主线程是可以操作的,比如界面上有个按钮,你是可以按的 而不是如上面的同步,在10面期间,我是只能干等着,什么都做不了。 异步的核心概念就是一个新线程,一个消息回调通知。 3.并行 我们还是以上代码为例。前面我强调了,我们只看一张图片的加载,现在,回到我们第一眼看到代码的思维上去, 一个for循环。其实上面代码过后,我是创建了10个异步线程。 好吧,到此,我们应该明白这三个概念了。 同步,其实我前面的例子举得有些局限,就是这个例子本身就说明不需要同步执行,然后给大家大感觉是 同步是编程中一个忌讳点一样,其实不然,很多时候。我们真是需要同步来做一些限制(比如线程中提出的同步锁?听着就感觉有用么 虽然可能并不如我们想的那样的运用同步,但是至少说明这个概念同样是有用的) 我还是以刚才那个加载图片为例子,来个简单的说明如何运用同步的好处。 当然,我只是模拟一个同步的情况。 假设我们现在图片的加载是这样的,图片本身为在加载前是一个默认的图片,上面写着,点击我加载,点击后会调用网络加载方法,然后图片显示加载中, 然后我们双击图片时(当然,理论上是在加载完后)读取图片网络图片放大,好吧,到这里应该能想到要表达的情况了。 整个流程应该是点击图片->加载->双击查看。那如果成了点击->加载中(以返回了图片的作者和信息)-》双击图片(通过前面请求返回的大图链接显示大图)-》 完全加载返回(返回了大图链接)。此时我们看不到图像的大图了。因为我们操作在返回前了,也就是说, 很多时候,我们下一个动作的操作必须需要用到前面一个操作的数据时,我们会给他做认为的同步编程,比如加个按钮锁。 这是我们又会疑惑道,下一个执行需要用到前一个执行的,那第一个例子中的for循环的第二句不是要用到么,这么说 他们必须要同步啊,如果你这么想了,好巧,我们想到一块去了~ 但是,注意,前面我们到的异步是为了解决我点击其他按钮的操作,而不是说更新UI操作。下载和更新UI操作在我们看来必须是同步的 这是对的,但是那种做导致了系统本身一些监听事件监听到点击处理在那个请求之后了,这边的加载图片其实要看成一次事件执行, 因为对于事件的这一抽象单元,其实是一种可人为定义的宽广度。 也就是说,一次数据获取和图像填充,其实算是一个图像获取加载事件,事件可以说包含两个单元,加载和填充。 而整个这个事件对于我们点击其他按钮并无关系,那么也就说明了无需同步。 有道理啊,但是若果我们要点击这个图片呢,也就是回到刚才那个可以双击的假设。 此处也许我么又忽略了一点为什么加载中我们能点击双击呢,也就这样的假设是获取图片已经做了异步,但是我们下一步操作又是需要同步的 因此做了人为的同步锁定。 好了,说的太多了,当时至少我们明白两点 异步可能是为了反正耗时操作造成的主线程堵塞, 同步是为了解决一些不必要错误和麻烦。也许到这里,我们脑中会联想到的所谓的线程安全性。 其实同步以及同步锁,却是应该是考虑到这样的不必要和不安全因素。 最后在简单阐述下异步和并发关系。 其实看了上面说的,异步只是提供了一种多线程处理的概念, 并发是更像是异步的一种大规模实现。 就好比说,异步提出了可以用小弟去收保护费,收完了告诉并交给自己,而我在期间做其他要做的事。 并发突然想到,异步这个很有道理啊,那我有4个地方要收,一个小弟去收,虽然我还是可以闲着做其他的事, 但是小弟跑四个地方,我拿到钱所需要的时间还是和我自己去收一样的,只不过我不用那么费劲了,还能做其他事了。 因此,并发觉得应该派四个小弟去,因为每个场地的保护费各不相干的。(刚看了个纽约黑帮~)。 因此说,异步解决了线程堵塞,而并发则是在异步的基础上,提高了符合特性事件的处理时间效率。 当然,如果10个图片本身相互间是没什么联系,但是,最后一个事件需要处理计算这10个图片的总容量值。 那么可以用 dispatch_group_async。 具体就看文档吧。 总体来说,看了iosGCD这块,一是让我熟悉了block编程特性,还有是熟悉如何使用ios提供的GCD特性 来完成多线程编程。

下载文档到电脑,查找使用更方便

文档的实际排版效果,会与网站的显示效果略有不同!!

需要 6 金币 [ 分享文档获得金币 ] 2 人已下载

下载文档