如标题所示,这里边记录了一个android开发人员学习iOS开发的笔记。
由于之前主要做android,所以会用java和android里边的知识点与objective-c和iOS的做对应,这样理解起来更快。
Objective-C基础知识
Foundation框架里边的常用类
- 值对象
- 字符串
- NSString - 不可变字符串,相当于Java中的String
- NSMutableString - 可变字符串,类似于Java中的StringBuilder。
- 数值:NSNumber,它可以赋值各种数值类型的值,如char, short, int, long, float, double,甚至BOOL。这个类比较”强大”,在Java中找不到单独对应的类。
- 日期:NSDate,表示日期。到现在并没有使用过,看起来应该对应于Java中的Date。
- 二进制数据
- NSData,不可变二进制数据。相当于Java中的byte[],即创建后内容不可变。
- NSMutableData,顾名思义,可以修改的二进制数据。相当于Java中的ByteBuffer,即一个字节缓冲区。
- NSValue,可以存放基本数据结构, struct, enum, nil等数据类型。相当于Java中的包装器,即int - Integer, byte - Byte, float - Float等。
- 集对象
- 数组
- NSArray - 不可变数组,相当于Java中的数组。同样都是初始化后值不可变,但是它并不要求每个元素都是同一个类的实例。
- NSMutableArray - 可变数组,这个我觉得还是很像Java中的List,确切的说是ArrayList。至于在Objective-C中有没有响应的”LinkedList”,这个我还不清楚(毕竟刚入门,: ))。
- 集合
- NSSet - 不可变集合,相当于Java中的Collections.UnmodifitableSet。
- NSMutableSet - 可变集合,相当于Java中的HashSet(不排序)。
- 字典
- NSDictionary - 不可变字典,相当于Java中的Collections.UnmodifiableMap。
- NSMutableDictionary - 可变字典,更像Java中的HashMap。
编写自定类相关
- 接口,此接口非Java的接口,而是C/C++的头文件
- 实现,相当于C++的cpp文件,只不过后缀名是”.m”
- 属性,储存对象的数据,用@property来做修复符,相当于Java的成员变量。
- 公共访问,将属性声明在接口文件中
- 私有访问,将属性声明在实现文件中
- 只读,使用(readonly)修饰表示该属性只读,类似于Java的成员变量加上final修复符
- 方法
- 类方法,使用”+”表示,相当于Java中的静态方法
- 实例方法,使用”-“表示,相当于Java中的成员方法
- 公共方法与私有访问的实现方式与上面的属性一样
- 方法参数,这个对于新手(尤其是其它语言转过来的人)来说,是语法上最奇怪的一个方面。不太好描述,附上几个简单的例子
- 没有参数:
- (void)markAsCompleted;
,方法名是”markAsCompleted”
- 一个参数:
- (void)markAsCompleted:(BOOL)isComplete;
,方法名是”markAsComplete:”,即”:”作为方法名的一部分
- 两个参数:
- (void)markAsCompleted:(BOOL)isComplete onDate:(NSDate *)date;
,方法名是”markAsComplete:onDate:”,注意这里的”onDate:”是方法名的一部分
- 三个及以上参数:以此类推…
- 协议:这个才是Java中的接口,主要用于实现回调
- 修饰符
- copy, 在复制时重新创建一个新的变量,参考iOS中copy的用法
- atomic, nonatomic,参考 ios atomic nonatomic区别
- instancetype, 表示方法的返回类型与调用方法的对象类型相同,作用是子类继承过去的方法也可以返回正确的类型(如初始化init系列方法)
- id, 引入instancetype之前,初始化方法的返回类型都是id。它是指向任意对象的指针,与instancetype相比,它还可以用于表示变量和方法参数的类型
MISC
KVC(键值编码)
可以使用这种机制来访问变量的属性,即使该属性没有get/set方法也可以调用。与Java中反射读写对象变量的机制很是类似。
具体可参考:objective-c中的cocoa特性:KVC-键值编码(十三)
iOS知识
UI
app状态及切换
app各种状态的特性
国际化/语言本地化
原理和android类似,都是将要显示的文字单独抽出来放在专门的文件中,android是放在strings.xml中,iOS则是放在Localizable.strings文件及Storyboard.strings文件中(如果Storyboard中也有需要本地化的字符串)
具体操作可以参考这篇文章:iOS应用国际化教程(2014版)
可视化开发布局
- storyboard,apple官方中文翻译为”串联图”。可以定义多个界面,并且定义它们之间的跳转关系(猜测”串联”应该由此而来)
- xib,与storyboard相比较为轻量,用于描述局部的ui界面。这让我想到了android写布局的layout xml文件
- autolayout,ios6开始引入的技术,目的是为了自动适配多种屏幕的设备。具体用法这里没有必要“复制-粘贴”,网上有很多“如何使用”的教程。目前我只简单的用过storyboard写ui界面,感觉ViewController的View(相当于android的ViewGroup)很像一个RelativeLayout,而auto layout增加的各种constraints,则对应于android中RelativeLayout的child view可以设置的各种相对parent view或sibling view的属性。
- 理解对齐矩形的概念
- 容易出现的3种问题:有歧义的布局、约束缺失、视图位置错误
- 代码调试:hasAmbiguousLayout, exerciseAmbiguityInLayout
- 控制台调试:输入命令
(lldb) po [[UIWindow keyWindow] _autolayoutTrace]
代码布局
- 如果创建整个视图层次结构及所有视图约束,覆盖loadView方法
- 如果只是向通过nib文件创建的视图层次结构中添加一个视图或约束,就覆盖viewDidLoad
一些概念的理解
- scene:对应用户来说就是app中的一个页面(整个屏幕的界面),这更多的是一个概念。对于ios开发来说就是viewcontroller,而android来说就是activity。
- viewcontroller:是一个controller,它持有root view的引用,这样你可以遍历叶结点或任意的子view。相当于android中的activity。
- segue:连接不同viewcontroller的纽带,它在作用上有android中的Intent有些像,比如切换不同的界面,传递数据。但segue使用上更加方便,它是直接在两个viewcontroller里的view之间建立关联,一个按钮的触发到另一个view controller的启动(这些在android里边要手动写对应的逻辑)。可以分为如下集中形式:
- show:将新的内容push到当前view controller stack的顶部
- show detail:将新的内容push或者replace到当前view controller stack的顶部
- present modally:与android中的dialog类似
- 一个view controller模态地展示另外一个controller
- 不会添加到navigation controller
- 通常认为是所显示view controller的child
- popover presentation:这个的作用与android中的popupwindow一样
- custom:继承UIStroyboardSegue,自己实现transition
- unwind:可以返回一个或多个segue,即将用户带到前一个或者前几个界面
- relationship:另外一种连接view controller的纽带,不过官方的doc里边只提到了一种场景 - 包含,即navigation controller和它的root view controller。
常用UI控件(UIKit views)
- 内容(Content):显示特定对象的内容,例如图像或者文本
- UIImageView,相当于android中的ImageView
- UILabel,相当于android中的TextView
- 集(Collections):网格布局或者列表布局
- UICollectionView,相当于android中的GridView
- UITableView,相当于android中的ListView(不要被名字里边的”table”所迷惑)
- 控制(Controls):执行操作或显示信息
- UIButton,相当于android中的Button
- UISlider,相当于android中的SeekBar
- UISwitch,相当于android中的Switch
- 栏(Bar):用于导航或执行操作
- UIToolBar,在屏幕底部显示的工具栏
- UINavigationBar,在系统状态栏之下显示的导航栏,与android中的ActionBar有些像
- UITabBar,在屏幕底部显示的Tab栏,类似于android中的TabHost(TabHost默认是在顶部显示的,如果要在底部显示,需要一些技巧)
- 输入(Input):接收用户输入的文本
- UISearchBar,搜索输入栏目,类似于android中的SearchView
- UITextView,相当于android中的EditText
- 容器(Containers):其它View的容器,即android中的ViewGroup
- UIView,有些像android中众多ViewGroup中的RelativeLayout
- UIScrollView(见谅,刚入门,目前还不清楚是否支持横向滚动),相当于android中的ScrollView
- 模态(Modal):中断应用程序的正常流程,允许用户进行某种操作
- UIAActionSheet,从屏幕底部弹出的对话框,里边有几种用户可以执行的操作
- UIAlertView(iOS8开始已经过时,建议使用UIAlertController),类似于android中的AlertDialog
事件传递链&事件响应链
顺序大致如下
- 事件传递顺序:UIApplication->UIWindow->UIViewController->UIView->XXXView
- 事件响应顺序:XXXView->UIView->UIViewController->UIWindow->UIApplication
参考:iOS中的事件传递和响应者链条
数据持久化
优缺点比较
固化
是iOS SDK提供的一种保存、读取对象的机制。
类似于Java中的对象序列化(与反序列化)。
被固化的对象需要实现NSCoding协议,它包含两个方法initWithCoder:
,encodeWithCoder:
。
通过NSKeyedArchiver
和NSKeyedUnarchiver
类进行持久化操作。
文件
- 读写二进制数据可以
NSData
- 读写文本数据可以使用
NSString:initWithContentsOfFile:
, NSString:writeToFile:atomically:encoding:error:
Core Data
提供对象-关系映射(object-relational mapping)功能。
其中Entity对应表格,attribute对应列/属性。
使用Xcode向导创建的xcdatamodeld文件,可以在里边创建Entity,attribute,relationship等,类似于可视化的数据库管理软件。
如果要创建的attribute的数据类型Core Data不支持(如UIImage),可以使用Transformable类型,并且编写NSValueTransformer
的子类来指定转换过程。
相关的类有:
- NSManagedObject - Entity转换过来的实例类的基类
- NSManagedObjectContext - 负责应用和数据库之间的交互工作,类似于android中的
SQLiteDatabase
类
- NSPersistentStoreCoordinator - 指定文件路径,打开响应的SQLite数据库
- NSFetchRequest
- NSPredicate
- NSSortDescriptor
- NSSortOrdering
- NSExpression
- NSExpressionDescription
关系占位符 - faults
设计模式
是什么
是抽象设计,而非代码
即独立于各种语言而存在
采用一种设计,就是应用它的通用模式来解决特定问题
有什么作用
为什么要使用
- 有助于更高效地使用框架
- 可以使得编写的程序复用程度更高、扩展性更强和更容易修改
常见的几种设计模式
MVC
MVC是任何设计良好的iOS app的核心。MVC将app中的对象分配到三种角色的一个:模型、视图和控制器。
- 模型:模型记录了app中的数据
- 视图:显示用户界面,填充app的内容(将模型对象中的数据呈现给用户)
- 控制器:管理视图;通过响应用户操作与从数据模型中获取的内容填充视图,控制器作为模型与视图之间沟通的关口。
# MVCS
这是对MVC的拓展,S指的是Store(存储),即将数据持久化从Control中独立出来,使其减轻“压力”。
而Store则可以借助多种途径来进行数据持久化操作,如文件、数据库、Web服务或者其它。
目标-操作
当某个特定的事件发生时(例如按下按钮),发生事件的一方会向指定的目标对象发送一个之前设定好的动作消息。
注意:针对不同的事件,需要创建不同动作消息。
类似于Java中为UI控件设置事件监听器,但是Java中的监听器是实现了指定接口的类的对象(接口里边可以有多个方法,可处理多种情况的事件),而”目标-操作”机制则只限于一种事件。
委托
作用上与目标-操作相似,被委托的对象在事件发生时向委托对象发送响应的消息,由委托处理该事件。
但与目标-操作相比,一个委托可以发送多种事件消息。
常见错误/问题
- application windows are expected to have a root view controller
- iPhone6/6Plus下app状态栏内容放大问题处理
- iOS9 HTTP 不能正常使用
MISC
通知 - NSNotificationCenter
与委托、目标-操作类似,通知也属于回调的一种。与前两者不同的是
委托、目标-操作需要对象直接向自己的委托或者目标发送消息,而通知使用一个中介 - NSNotificationCenter。
注意,它与通知栏中看到的通知:推送通知(push notificatioin)和本地通知(local notification)无关,NSNotificationCenter只用来处理应用内部的对象通信。
通过它,对象可以注册感兴趣的系统事件,如内存过低警告(UIApplicationDidReceiveMemoryWarningNotification)、设备旋转(UIDeviceOrientationDidChangeNotification)
iOS技术
指的是iOS提供的各种供开发者使用的框架
UI
- UIKit
- Core Graphics
- Core Animation
Game
- Game Kit
- Sprite Kit
- OpenGL ES
- Game Controller
Data
Media
学习路径
- 初步了解 - 《Start Developing iOS Apps Today》
- Objective-C语言学习 - 《Programming with Objective-C》
- 进一步了解 - Apple官网上的一些Sample
- 系统学习 - 《iOS编程(第4版)》
参考
- Difference between a Scene and a View in iOS