微信号:cocoachinabbs

介绍:CocoaChina苹果开发中文社区官方微信,提供教程资源、app推广营销、招聘、外包及培训信息、各类沙龙交流活动以及更多开发者服务.

写给前端看的 iOS 梳理 (上)

2018-02-10 22:00 Tw93



去年双十一为了排查一些 Weex 性能问题开始接触 iOS 相关学习,恰逢今年 1 月份开始慢慢参与 iOS 业务开发,借此机会整理一下 iOS 开发中的一些基础知识,用于备忘,同时旨在通过系列文章让前端同学在日后碰到 iOS 的代码可以看懂,方便更好的理解端上的一些原理。


大纲


《上》主要讲述在 iOS 的开发过程中碰到的文件格式和 Foundation 框架常用的类,《中》和《下》正在整理中,同时文中图片建议点击查看原图


文件格式


  • .h: 头文件也叫接口文件,提供对外访问的接口,包含类、方法和属性的声明,相当于类的用户手册

  • .m: 实现文件,用于实现 .h 中声明的方法,相当于类的工程细节

  • Podflie: 包管理文件,用于定义项目所需要使用的第三方库,类比 package.json

  • Podflie.lock: 依赖库锁文件,记录了需要被安装的 pod 的每个已安装的版本,便于团队协作包统一,类比 package-lock.json

  • .xib: 可视化文件,一个轻量级的用来描述局部界面的文件

  • .storyboard: 界面布局文件,承载对应 UIView 的视图控件

  • .pch: 预编译头文件,将一个工程中“不会常修改”代码预先编译好放到 pch 里面,用于存放公用宏、存放公用头文件、还可以管理日志输出

  • .plist: 属性列表文件,一种用来存储串行化后的对象的文件,通常用于储存用户设置或者一些捆绑的信息,也是数据持久化解决方案之一

  • .lproj: 多语言本地化文件夹,也即为每一种语言单独定义一份资源,有图片,文本,Storyboard,Xib 这些文件

  • .xcassets: 图像资源文件,用了存放图片资源

  • .xcodeproj: Xcode 工程文件,存储着 Xcode 工程的各项配置参数

  • .xcworkspace: Xcode 工程文件,使用 pod install 后生成的新文件,打开后可以同时看到项目文件和 pods 依赖包


Foundation 框架


简要介绍


首先介绍一下 Cocoa,Cocoa 是一套 OS X 和 iOS (Cocoa Touch) 中的框架和运行时支持,也即 API 应用程序接口,可类比于 VC 里面的 MFC。


Cocoa 其中最重要和 UIKit(OSX 为 AppKit) Foundation,两个框架在系统中的位置如下图, 同时可以看到常见的框架所在位置。



其中 UIKit 主要用于 iOS 界面构建的,后面详细介绍。


Foundation 框架给我们框架和 App 开发提供了基础层功能,用于访问基本的数据类型,集合和操作系统服务,包括如下:


  • 数据存储和持久化:NSArray、NSDictionary 以及 NSSet 为任何类的 OC 对象提供存储

  • 文本和字符串处理:NSCharacterSet 用于 NSString 和 NSScanner 类中字符串各种操作

  • 文件处理:NSFileManager 类 提供大量用于文件操作检查的方法

  • 日期和日期:NSDate、NSTimeZone 和 NSCalendar 类

  • URL 操作:提供一组类和协议来处理 URL 访问

  • 异常处理:NSException 类


Foundation 在 JS 里面可以假想成一个原生的公用 Util 库,But 没有...


开始之前


OC 中@是做什么的 ?


  • 通常字符串前面会加一个@,用来将一个 C 语言的字符串转化为 OC 中的字符串对象 NSString

  • @ 符号 OC 中大部分的关键字都是以@开头的,比如 @interface,@implementation,@end @class等


很多类之前的 NS 前缀是什么 ?


  • OC 里不支持命名空间,所以只能通过加前缀这种土土的方法来避免命名冲突,所以常常会用 3 个大写字母(2 个的被苹果占了),可譬如开发者名称、公司名称或者方法名等来区分

  • NS 代表的是 NextStep,是 Jobs 在 1985 年离开水果的时候创建的公司名称,后来被收购回来后,很多成果被吸收到 OSX 基础中

  • 类似的还有,CF == Core Foundation;CG == CoreGraphics.frameworks;CA == CoreAnimation.frameworks;UI == UIKit 等表示


对象的可变性


OC 中的类可分为可变(mutable)类和不可变(immutable)类,这里不可变指的是字符串在内存中占用的存储空间固定,并且存储的内容不能发生变化,反之可变是指占用空间可不固定,内容可修改;这个和灵活的 JS 是很不一样的,但我更倾向于对数据类型区分可变和不可变,也便于后续的维护和扩展。


对于确定不会改变的类,它只具备应有的属性方法,可变类通过继承原有不变类,再增加可变方法属性即可实现可变。


可变类是不可变类的子类,同时所有可变类的实例对象可以作为不可变的实例对象来使用。


NSString


在 OC 中使用 NSString 来表示字符串,可变 NSMutableString 继承不可变 NSString 类,好比一个字符串链表,可对其进行 增删改 操作。



NSArray


在 OC 中使用 NSArray 来表示数组类, 这里需要注意的是它不像 JS 的数组可以存入任何类型,在 NSArray 中只能够存入 OC 对象,同时也是不可变的,假如需要更改数组,需要使用它的子类 NSMutableArray。



通过arrayWithObjects方式创建的数组记得在最后一项加上nil,所以为了方便更推荐直接使用@[@"lnj", @"lmj", @"jjj"]方式创建,但是因为生成的是不可变数组,故在 NSMutableArray 中不要这么创建。


很多数组的操作方法和在 JS 中对比大致相同,不过 NSMutableArray 提供了比 JS 中一些更丰富的方法,包括交互两个元素位置这种需要自己写的方法,也即很多时候编写时候可以先查查文档看是否有这个方法, 很多时候可以从里面找到。


NSDictionary


前端同学第一次听到字典这个词可能会有些陌生,可以类比 JS 中的 Object, Java 中的 Map,字典中的数据也是通过键值对保存。


NSDictionary 属于不可变字典类,一般创建之后只能用于查询,不能对其进行修改操作,想修改需要使用 NSMutableDictionary 类。



NSDate


NSDate 可以用来表示时间, 用来进行一些常见的日期时间的处理,它的使用方式和 JS 的 Date 也是很相似的,[NSDate date] 返回的就是当前时间,但是在格式化日期时间上面 Foundation 处理比 js 要优雅很多,直接调用其内置方法即可。


通过和 NSDateFormatter 类配合使用可以格式化日期,stringFromDate用于 NSDate 转 NSString,dateFromString用于 NSString 转 NSData:


//NSDate 转 NSString

NSDate *now = [NSDate date];

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";

NSString *str = [formatter stringFromDate:now];

NSLog(@"%@", str);


// NSString 转 NSDate

NSString *str = @"2018-02-08 11:53:12";

NSDateFormatter *formatter = [[NSDateFormatter alloc] init];

formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";

NSDate *date = [formatter dateFromString:str];

NSLog(@"%@", date);


假如想在时间日期上面处理更复杂的内容,还可以借助 NSCalendar 类丰富我们的处理:


NSDate *date = [NSDate date];

NSCalendar *calendar = [NSCalendar currentCalendar];

// 利用日历对象获取年月日时分秒

NSCalendarUnit type = NSCalendarUnitYear 

                    | NSCalendarUnitMonth 

                    | NSCalendarUnitDay 

                    | NSCalendarUnitHour 

                    | NSCalendarUnitMinute 

                    | NSCalendarUnitSecond;

// cmps 包括 year、month、day、hour、minute、second 属性

NSDateComponents *cmps = [calendar components:type fromDate:date];


比较日期,可以直接使用如下方法:


- (NSDateComponents *)components:(NSCalendarUnit)unitFlags 

      fromDate:(NSDate *)startingDate 

      toDate:(NSDate *)resultDate 

      options:(NSCalendarOptions)opts;


从上面看,OC 中很多方法都是很长很长的,并且将每一个参数代表的意思也表示出来了,不会出现错误对应的情况。


NSURL


写前端久了会慢慢觉得 URL 就是一条线上的链接 H5 地址,其实不然,URL(Uniform Resource Locator)中文意思是统一资源定位符,除了 http 协议之外,还有https/ftp/file协议用来访问一个资源。


在 OC 中,操作 URL 时候应该用专用的 NSURL 类,而不建议把 URL 当做字符串来手工解析。



随着后面的升级,原来在 OS 中很多文件输入输出的地方也开始使用 NSURL 了,也即慢慢地将网络当时 OS 中的一部分了。


NSNumber \ NSValue \ NSNULL 包裹类


Cocoa Fundation 框架的集合类(NSArray\NSDictionary\NSset)中只可以放入对象,前端同学可能开始时候会很不适应,假如想放入 int\float\double\bool 等基础类型,需要将其包裹成 OC 对象在进行放入,这里就需要使用 NSNumber 包裹类了,才能间接的将基础类型放入。


// 直接在前面加入@就可以创建一个 NSNumber 对象型

@10;

@10.5;

@YES;

@(num);


// NSNumber 类提取基础型

- (char)charValue;

- (int)intValue;

- (double)doubleValue;

- (BOOL)boolValue;


但是对于结构体、指针这种复杂的数据类型,NSNumber 也无法包裹,这里需要使用 NSValue 类,它是 NSNumber 的父类,可以将任意类型包装成对象。


// 结构体包裹,譬如 NSPoint、NSSize、NSRect

- (NSValue *)valueWithPoint:(NSPoint)point;

//从 NSValue 对象取出之前包装的结构体

- (NSPoint)pointValue;


前面的数组字典中是不能自己放入nil的,因为在里面有结束的含义,但是有时候我们又确实需要一个特殊的对象来表示空值,这里就需要 NSNULL 了,可以通过类方法 +(NSNull *)null 来定义,同时可以通过if(obj==[NSNull null])来判断是否为 NSNull。


实际开发中极少使用NSNull,而且一般习惯也不会单独判断这个(默认大家都不用),所以用它也会很危险(大多数情况是用nil,nil可以接任何消息,但 NSNull 不行,二者特性的区别可能引起crash)。


小结


通过以上文章,最多只能够让大家对 OC 编程有一些了解,谈不上深入,更多的是希望前端对于 H5/Weex 的深入了解和优化不要局限到最上面薄薄的一层,完全可以联系到底层的加载、渲染、图片库、网络库等等来进行优化。


从语言层面来说,OC 和 JS 还是挺有意思的,变量/方法命名的风格正好相反,苹果更加鼓励开发者程序命名尽量使用英文全称并且是尽可能详细,通过看到方法和变量就知道是做啥的,看写得好的 iOS 仿佛看散文一样,譬如 -(NSArray *) componentsSeparatedByString:(NSString )separator; 分割字符串,在 JS 里面直接通过 str.split() 就解决了,更多前端开发者习惯不长的命名,因为需要从网络下载,尽管压缩工具会做,但大家也习惯短命名来表示。


由于编译型语言缘故,写 OC 过程中很多错误可以在编译过程就发现,同时运行速度快,同时很多事情苹果都帮开发者做了,包括工程体系,这样其实写 iOS 可发挥的地方没有前端多;反之 JS 为解释性,性能更多依赖于引擎,加上为语言动态,写起来也爽,很多奇淫技巧可使用,加上 Node 的发展,让其可以做很多有趣事情。


各有优点,喜欢 Web 的快速和开放,也爱 iOS 的优雅体验和统一化


假如你可翻墙,也可以来GitHub Pages看 写给前端看的 iOS 梳理


 
Cocoa开发者社区 更多文章 Weak-Strong-Dance真的安全吗? iOS笔记 | Pointer is missing a nulla [译]用 LLDB 调试 Swift 代码 程序员以上帝视角解读“旅行青蛙”,你的呱真的在旅行嘛? 阿里数据iOS端启动速度优化的一些经验
猜您喜欢 如何成为在硅谷受欢迎的程序员? 春节读者调查 & 新栏目建议征集 别人没看到的要害,独家解读习总访美成果清单丨智谷趋势 django-MySQL数据库 途牛首届编程大赛今日火热开赛!