iOS 实战开发课程笔记
本贴旨在作为对极客班 《iOS 开发实战》第五期期课程视频重新学习的笔记。
目标是建立一个比较完整的 iOS 开发知识点框架以及快速手册。
对各个内容的详细研究会开启新贴深入探究。
该贴仍在不断完善中。
0 导论
0.1 技术支持
0.1.1 苹果技术支持
- 技术文档打开方式
Xcode软件 -> Help -> Documentation and API Reference
文档是在网上读取的,如果想要更加快速,可以先进行下载。旧版本的模拟器也在这里安装。
Xcode -> Preferences -> Downloads - 开发者社区 https://developer.apple.com
- iOS文档库 https://developer.apple.com/library/prerelease/ios/navigation/
- WWDC 视频
0.1.2 其他技术支持
- stack overflow 社区
- OurCode 社区
- Cocoa China 社区
- V2EX 社区
- GitHub (建议查看学习 awesome iOS 系列)
0.2 学习方法
0.2.1 方法
- 认真看视频。
- 整理笔记。
- 完成练习示例。
0.2.2 参考书
- ios 9 programming fundamentals with swift
- ios 7 programming fundamentals (Objective-C)
0.2.3 App Programming Guide for
界面基础
View Controller Programming Guide
View Controller Catalog
View Programming Guide
UIKit User Interface Catalog
Event Handing Guide图形和动画
Drawing and Printing Guide
Concurrency Programming Guide
Quartz 2D Programming Guide
Core Animation Programming Guide网络与存储
Network & Internet Starting Point (知道个方向)
Networking Overview (了解个概念)
Data Management Starting Point (知道个方向)其他
Auto Layout Guide
Scroll View Programming Guide
Table View Programming Guide
Collection View Programming Guide
1 Hello Word
1.1 创建新工程
- Create a new Xcode project
- File -> New -> Project [shift + command + N]
1.2 选择工程模板
可以选择多种多样的工程模板,包括 iOS, OS X, watchOS, tvOS 一般选择 iOS -> Single View Application。
1.3 工程信息
- Project Name:产品名称
- Organization Name:组织名称
- Organization Identifier:新产品唯一名,一般把公司域名反过来写。
- Language:运行语言
- Devices:运行设备(通用,iPhone,iPad)
- Use Core Data:是否使用数据存储
- Include Unit Tests:测试模块
- Include UI Tests:UI测试模块
1.4 Git 仓库
版本控制
Source Control:Create Git repository on My Mac
后续版本控制有专门篇幅。
1.5 Xcode界面了解
1.6 Storyboard
- 图层识别
选中图层之后,可以在 libraries -> identity inspector -> Document -> Label 中设置图层名称,可以更改图层在 Storyboard 的 Document Outline 中的名称。以方便识别。 - 组件 library
可以拖动这里的各种组件到 canves 或其中对应的图层上。 - 设置 Document Outline 显示名称
选中组件 -> Indentity inspector -> Document -> Label - 设置 ViewController 尺寸
选中 ViewController -> Attributes inspector -> Simulated Merices -> Size
1.7 模拟器
- 显示尺寸调节
Window -> Scale -> … [command + 1-5] - 设备操作
Hardware -> … - 返回出厂设置
Simulator -> Reset content and Settings…
1.8 真机调试
- 添加调试账号
Xcode -> Preferences -> Accounts -> + - 设置调试账号
Workspace -> General -> Identity -> Team 进行选择 -> Fix issues - 运行
首次运行会提示错误,需要真机验证
真机 -> 设置 -> 通用 -> 描述文件 -> 选中信任 -> 回到 Xcode 再次运行
1.9 App 基本概念
- iOS App 代码结构(这是 Objective-c 语言,Swift 有所不同,main 文件会被隐藏)
- main()
- UIApplicationMain()(生成一个 UIApplication 对象并设置成为该应用的代理。)
- UIApplication 对象
- UIApplicationDelegate
- iOS App 运行环境
- Sandbox
- 获取目录 NSHomeDirectory()
- iOS 应用都是一个 Bundle
- Bundle: 带有 Info.plist 字典的目录
- 通过 NSBundle 类访问其中的资源
- 主要是通过 mainBundle
- resource bundle 和 framework(可执行动态库)
- 查看 App Bundle
设置栏中选择设备 -> Generic iOS Device -> command + B 构建 -> Workspace -> Products -> xxx.app -> 右键 查看文件 -> 右键 显示包内容
3 Button - Storyboard 与代码之间联系方式
介绍最常用的 Interface 组件之一 UIButton,以及它的使用方法。
从而介绍 Outlet Action 等概念。
3.1 UIButton
3.2 IBOutlet
IBOutlet Connection
把 Nib object 与 代码中的 IBOutlet 变量相连接在 Storyboard 中将组件与代码中的 IBOutlet 变量进行连接后,会在 Storyboard 代码中多出来这样一段连接说明
<connections> <outlet property="okLabel" destination="QJt-2z-ban" id="mhJ-Nu-TIR"/> </connections> // property 变量名称 // destination 界面上的组件名称 // id 标志这个连接本身
运行时调用
由于 xib 中存储的是界面模板,所以在允许的时候,类实例代码会触发界面的实例化方法。
最终调用[UINib instantiateWithOwner:options:]
方法实例化界面。
Owner 实际上是调用了一个按名字绑定的属性。[owner setValue:uiObj forKey:outlet.property]
其实我自己都看不懂这段在说什么……大概是说 outlet connection 其实是标注了界面与代码之间的关系,然后在程序运行的时候,会通过一系列 runtime 方法调用这种关系,并根据界面模板实例化界面组件,从而生成组件绘制吧。
Action Connection
界面事件连接 IBAction
<connections> <action selector="buttonAction:" destination="BYZ-38-t0r" eventType="touchUpInside" id="BQA-pw-9f8"/> </connections> // selector 方法名称 // eventType 事件类型
4 Image
图片流:界面全部由现成的图片构成。耗内存,但是简便。
代码流:界面全部由代码绘制而成,省内存,适应性高。
4.1 UIImage
图片加载
图片动画
let anmiationImage = UIImage.animatedImageNamed("ImageArrayName", duration: 2.0) // ImageArrayName 是动画图片的前缀,动画图片资源应该按照该名称后面加数字来命名。 // duration 是总时长。 // KeyNote 可以导出动画的每帧图片。
4.2 Assert Catalog
Assert Catalog 介绍
模板会默认生成一个 Assert Catalog 文件并且其中有 Appicon 以用于给 App 提供系统图标。
直接用图片名字的办法加载图片,虽然简便,但是由于这样的做法会把图片缓存在内存中,在图片较多尺寸较大时会照成内存压力。Assert Catalog 功能
- 添加图片:直接将图片资源拖入 Asset Catalog,或者下面的
+
号。 - 资源属性:每个图片可以有三个尺寸以提供给不同的屏幕尺寸使用。还可以设置适用各种设备和各种特定尺寸 Attributes -> Devices。
图片切片:点击图片 -> Attributes -> Slicing -> Slices -> …
- 添加图片:直接将图片资源拖入 Asset Catalog,或者下面的
适用矢量图片
- 放置对应的图片格式进去 Assert Catalog 之后,然后设置其属性。
Attributes -> Devices -> Scale Factors -> Single Vector
5 第一个 App
5.1 需求分析
- 详细了解应用需求,需要确切了解用户想要的是什么。
- 详细规划应用的逻辑流程,各个模块功能的来由和去向。
5.2 程序设计
平衡设计原则:设计程序时为未来可能的需求做好准备。但是这种办法有好有坏,有时候考虑太多,就会导致当前事情难以完成。如果完全只考虑当前,就可能增加未来重构的次数。中间的度需要靠程序员把握。
- 走通流程图,确认游戏逻辑
- 确认静态数据结构
5.3 示例代码结构
各个代码模块之间的联系和关系的明确。
5.4 Keynote 课件展示
6 View Controller
6.1 简单的设计模式介绍
6.2 UIViewController
UIViewController 介绍
获取 ViewController
- 创建 rootViewController
- Info.plist 中的 UIMainStoryboardFile, NSMainNibFile 指定了根控制器的来源。
- UIApplication 会通过调用
_runWithMainScene:transitionContext:completion:
方法。 - 然后调用
_loadMainInterfaceFile
来取出 Info.plist 中 UIMainStoryboardFile 或者 NSMainNibFile 信息。 - 如果是前者,则再调用
_loadMainStoryboardFileNamed:bundle:
。 - 如果是后者,则再调用
_loadMainNibFileNamed:bundle:
。
- 加载好 rootViewController 之后就把这个视图控制器赋值给 appDelegate.window.rootViewController。
- 假如上述方法初始化界面失败,则会调用
UIApplicationDelegate didFinshLaunch
方法来给程序员一个使用程序初始化界面的时机。最开始时,也是只有这一个办法来初始化界面的。 - 如果以上两种办法都没有给
appDelegate.window.rootViewController
赋值,则这个应用的 window 就会为 nil 显示黑屏.
- 创建 rootViewController
获取 ViewController 的 View
- 自定义 ViewController 装载过程
- 调用
[UIViewController loadView]
如果有实现,调用之后就不会调用后面的方法了。如果是默认实现则会调用下面的其他方法。 - 调用
[UIViewController nibName]
如果是默认模板,则 nibName 应该是来自 Storyboard。如果是代码调用initWithNibName
则由程序员指定 nib. 如果两者都不是,则会调用下面的方法。 [UIViewController exisitingNibNameMatchingClassName:bundle:]
,它会根据 ViewController 方法猜测并且查找 Nib,如果都查找不到,系统会创建一个空白视图。
- 调用
- 要点
- isViewLoaded 判断 ViewController 的 View 是否已经加载好了。
- loadView 中不能调用 super.
- 自定义 ViewController 装载过程
6.3 View Controller Lifecycle
6.3 多个 View Controller
- 弹出新视图的方法
presentViewController:animation:completion:
- UIViewController 的 modalPresentationStyle 是设置弹出控制器风格的属性。
- UIViewController 的 modalTransitionStyle 是设置弹出动画风格的属性。
- iOS 8+ 之后新方法
showViewController:sender
- 释放控制器
dismissViewControllerAnimated:completion:
回传数据:把父控制器作为子控制器的代理,通过回调函数来传递数据。并且由父控制器来控制子控制器的释放,而不是子控制器自己调用
dismissViewControllerAnimated:completion:
方法。
7 Storyboard
Storyboard 也是一个 xib 文件,只是它里面不只是放 View,而是放置 Scene.
可以点击 ViewController 然后直接拖出 Segue 到其他 ViewController 当中,从而创建没有组件触发事件的 Segue。
7.1 Storyboard Segue
使用代码进行 Segue 跳转
func segueAction() { // 0 以 Segue 跳转 performSegueWithIdentifier("SegueIdentifier", sender: nil) // 1 获取 ViewController if let nextViewController = storyboard?.instantiateViewControllerWithIdentifier("ViewControllerIdentifier") { showViewController(nextViewController, sender: nil) } }
Segue 传值
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) { // 每次有 Segue 被触发就会调用此函数,以提供传值时机。 }
Storyboard Segue 回退
@IBAction override func unwindForSegue(unwindSegue: UIStoryboardSegue, towardsViewController subsequentVC: UIViewController) { // @IBAction func unwindFuncName(segueName: UIStoryboardSegue) { } // 名称可以随意,参数至少要有一个 UIStoryboardSegue。用来作为 Storyboard 回退触发事件。 }
7.2 多 Storyboard
当场景太多的时候,可以把 Storyboard 分成多个文件。场景之间的过渡,可以通过两种办法实现。
- Storyboard Reference 组件,跟 ViewController 组件一样可以拖动到 Canvas 上。并且可以设置它指向的 Storyboard 文件,Reference ID(如果不指定就是 initial View Controller)。
- 选中需要放置在新 Storyboard 上的 ViewController,然后点击 Editor -> Refactor to Storyboard。然后就会创建新的 Storyboard 文件,并将选中的 ViewController 放置到其中。
获取其他 Storyboard
func muchStoryboard() { // 根据名称获取 Storyboard let storyboard = UIStoryboard(name: "StoryboardName", bundle: NSBundle.mainBundle()) }
8 App Lifecycle
8.1 应用启动
- main - 启动程序
- UIApplicationMain() - 启动应用代理
- UIApplication - 启动消息循环
- APPDelegate - 生成应用代理
根据 Storyboard 或者代码创建的 ViewController 加载 rootViewController
8.2 用户互动
RunLoop Mode: [source] 其实就是事件源。
- main run loop 循环关注事件源。接收事件。
- 接收到事件就传递给 Application object。
- Application object 对事件进行分发。
事件根据代码逻辑反馈到视图上。
8.3 AppDelegate
出生
application:willFinishLaunchingWithOptions:
事件
UI 已经加载出来了。RootViewController 已经创建好,只是还没访问它的 view 方法。
应用级的初始化工作最好都放在这个位置,但是不要在这里做太耗时的事件。Options 会提供启动状态信息。
App Programming Guide for iOS 文档中的 Preserving Your App’s Visual Appearance Across Launches 中有详细的说明。application:didFinishLaunchingWithOptions:
事件
界面已经恢复过了,但是 UI 还没有放置到界面上。这时候代码已经开始执行,但是界面看不见,也不会进行响应。
依然是应用级别的初始化机会。Options 会提供启动状态信息。
applicationDidBecomeActive:
事件
应用已经要开始活动了的时机。
- 进入不活跃状态
applicationWillResignActive:
事件
- 进入后台状态
applicationDidEnterBackground:
事件
这是一个短暂的时机,默认是 5 秒内完成。但是可以通过beginBackgroundTask
方法可以获取大约 10 分钟的后台运行事件。
如果还需要更长的事件,需要编写后台运行程序。详细查阅文档。
- 应用关闭
applicationWillTerminate:
事件
如果你的应用刚好被挂起没有多久,然后就被关闭了,就会接收到这个事件。如果你已经被悬挂在后台了,那在关闭的时候就不会收到这个通知。
- 应用复活
applicationWillEnterForeground:
事件
应用即将回到前台的事件。
8.4 移动应用的特点。
移动应用的使用会非常的零散,会在各种状态中来回切换。