为什么要学ios?
因为部门要开始进行rn开发了。
- 为了能在开发前有更清晰的开发思路,以及在开发过程中能更好地定位问题和解决解决
- 在阅读rn文档的时候,很多东西不理解,比如:
- 为什么一定要用style,而不能用css?:因为cssom是web特有的,native的基础组件都是class,而样式都是考给class设置值来实现的,所以也更不用说啥样式的继承啥了。
- 标签为什么没有div span之类的,都是View Text之类的?: 答案和以上,这些标签也是html专用的,而安卓ios也没有什么dom结构。
所以决定学习一门原声语言,用iphone自然就选择了学ios。
怎么去学?
学习语言
不管你准备实战学习,还是看书学习,都得首先得看得懂代码,而客户端开发都有自己的语言,比如ios有swift object-c,而安卓有java、kotlin。我这里选择了学习swift,原因之一,这是ios推荐使用的最新语言;其次,他的语法相比oc来说,和JavaScript更相似一些。具体呢可以去看ios官方文档,英语没那么好也可以去看swift中文文档,这个中文文档真的相当可以。
山峦
想起原来学Vue的时候就是刷完了文档,然后再刷一套实战视频,跟着视频来一遍,基本上就可以算是入门了。再深入就只有持续开发来更熟悉来更累积经验了。这次学习ios也本打算这么搞,但是我真的没有找到质量好的实战视频。最终选择了看书,最后买了《ios开发指南》。
学习笔记
首先你需要安装Xcode,app store直接下载即可。
我这里的版本是:Version 11.3.1 。
基础
ios 原生UI开发方式目前主要有两种,一种就是故事板技术,文件后缀.storyboard,本质上就是拖拽生成界面,然后将界面和class关联(目前我个人的理解:ios最常见的代码单元就是一个类,一个UI视图也是一个类,所以在你拖拽生成的一个界面中,你想指定按钮点击事件等,就需要将这个页面和一个ViewController进行管理):
另外一种UI开发方式就是我们常见的代码来描述UI结构了,但是刚刚我们说了视图上的每个元素也都是一个类,所以在描述UI结构也是new一个class,声明长宽高等一堆属性,然后把它加入到视图中:
他们并没有像html一样的结构描述语言。这也是看rn教程 没有所谓
div
span
之类元素的原因。如果你用过一些canvas的库,你会发现这样的写法很那些很像,非常的原始,对于用惯了什么Vue React的人来说,这肯定写起来很累,并且效率很低(也是会出现rn的诱因之一吧?)。
注意:swift new一个类不需要关键字new。
创建项目
右上角 file -> new -> project -> single view app:
主要看Language和User interface,语言我们肯定选择Swift,然后就是UI,如果你想感受一下故事板技术,这里就选storyboard,如果不想用故事板,那么就直接选择Swift,纯代码构建。 如果不小心创建了storyboard那么可以重建一个项目,或者搜索 如何删除main.storyboard,网上会有一堆教程(因为原来的xcode版本默认创建的项目都是带main.storyboad的,所以网上有一堆教你怎么删除这个东西,用纯代码进行编程的)。最后三项对于入门来说暂时也用不到,直接不选就好了。第一项是是否用数据库(mobile phone本身就是一台储存比较小的计算机而已,所以是可以直接支持数据库的),后两项是单元测试、UI测试,如果选了其实就是在工程中会新增一些文件或者组。
目录结构
- AppDelegate:是应用程序的委托对象,继承了UIResponder类,实现了UIApplicationDelegate委托协议。简单来说就是操作App一系列生命周期的地方。(协议之后会讲到)
- SceneDelegate:ios13之后新加的分屏设计。原来没有这个文件,初始化根视图的操作之类的都在AppDelegate那个文件里写,但是新增的这个文件承担了部分它的功能,现在转而都在这里写了。(也有人闲大多数程序都不支持场景,所以会直接删除这个文件)
- ViewController:根视图的控制器,我们来写一个程序的第一个页面代码就都是在这里写的。
- Main.storyboard 和 LaunchScreen.storyboard:都是故事板,原来只有一个故事板,就是整个程序的UI设计,而现在新增了LaunchScreen,是加载app时,出现的屏幕UI设计。如果创建项目时User interface没有选storyboard就不会有Main那个文件,但是LaunchScreen还会保留。
- Assets.xcassets:防治各种资源文件的目录。
- info.plist:项目的各种配置,对应到前端的node项目的话有点package.json的感觉。且plist这个文件后缀,用其他编辑器打开,实际上是一个xml文件。
应用的生命周期
ios应用有5种状态:
- Not running(非运行状态):应用没有运行或者被系统终止。
- Inactive(前台非活动状态):应用正在进入前台状态,但是还不能接受事件处理。
- Active(前台活动状态):应用进入前台状态,能够接受事件处理。
- Background(后台状态):应用进入后台后,依然能够执行代码。如果有可执行的代码就会执行,如果没有或者执行完了就会进入挂起状态。
- Suspended(挂起状态):进入一种冷冻状态,不能执行代码,如果系统内存不够了就会被终止。
在状态进行跃迁的过程中应用会进行一些回调和一些本地通知:
方法 | 本地通知 | 说明 |
---|---|---|
application:didFinishLaunchingWithOptions: |
UIApplicationDidFinishLaunchingNotification |
应用初始化时会调用该方法并发出通知,会实例化根视图控制器 |
applicationDidBecomeActive: |
UIApplicationDidBecomeActiveNotification |
应用进入前台并处于活动状态时调用该方法,可以恢复UI。 |
applicationWillResignActive: |
UIApplicationWillResignNotification |
从活动状态进入到非活动状态调用该方法。保存UI状态。 |
applicationDidEnterBackground: |
UIApplicationDidEnterBackgroundNotification |
进入后台时调用该方法,可以保存用户数据,释放一些资源。 |
applicationWillEnterForeground: |
UIApplicationWillEnterForegroundNotification |
进入到前台时,但是没有处于活动状态,可以恢复用户数据。 |
applicationWillTerminate: |
UIApplicationWillTerminateNotification |
应用被终止,可以释放资源,保存用户数据。 |
一些场景
- 点击图标进入,或者程序被终止后进入:Not running -> Inactive -> Active (依次触发:
application:didFinishLaunchingWithOptions:
、applicationDidBecomeActive:
) - 点击Home键,应用退出场景:
- 应用挂起:Active -> Inactive -> Background -> Suspended (依次触发:
applicationWillResignActive:
、applicationDidEnterBackground:
,Inactive -> Background 不触发) - 不挂起(根据info.plist配置):Active -> Inactive -> Background -> Suspended -> Not running(比起上面 Suspended -> Not running多触发一个:
applicationWillTerminate:
)
- 应用挂起:Active -> Inactive -> Background -> Suspended (依次触发:
- 挂起重新运行:Suspended -> Background -> Inactive -> Active(Suspended -> Background不触发,依次触发
applicationWillEnterForeground:
、applicationDidBecomeActive:
) - 应用终止(在后台的应用因为内存不足而被终止):Background -> Suspended -> Not running (内存清除场景下不会调用任何方法和通知)。
目标
刚刚我们提到了plist里可以设置,程序切后台时挂起还是不挂起,这就是一个产品属性。而产品和目标直接相关,目标和工程本身又息息相关。
我们在file -> new -> target菜单里选single view page,可以新建一个目标:
最后一个Project选项就是目标关联的工程,点击finish就生成了一个目标:
目标包含一套完整的文件,且独立于原来的test存在。
想要运行哪个目标,就在目标中进行选择:
这其实就是一个方案(Schema),方案指一个要编译执行的目标,包括一系列配置信息,一个xcode可以包含n个方案。
产品属性
当我们点击每个target的根目录时,就会出现一系列选项:
我们常常根据产品需要来进行设置,比如屏幕方向、设备支持的情况这些常规信息,也有编译链接的库等信息。
ios运行原理
Main Run Loop
一个iOS应用程序的main run loop主要作用是处理所有与用户相关的事件。UIApplication对象在启动时就设置main run loop和使用它来处理事件和更新基于view的界面。正如它名字所示,main run loop是运行在应用程序的主线程。这样就确保与接收到用户相关的事件被有序地处理。
下图显示main run loop的架构和用户事件最终是怎样被应用程序处理。当用户与设备交互时,系统就会生成与交互关联的事件,然后被应用程序的UIKit通过一个特殊的端口来分发。应用程序把事件放入队列,然后逐个分发到main run loop来执行。UIApplication
对象是第一个对象接收到事件,然后决定怎样处理它。一个touch event通常都被分发到main window对象,然后依次分发到发生触碰的view。其他event的接收事件对象路径可能有点不同。
关键对象
UIApplication对象
用户与iOS设备交互时产生的事件(Multitouch Events,Motion Event,Remote Control Event)交由UIApplication
对象来分发给control objects(UIControl)对应的target objects来处理并且管理整个事件循环,而一些关于app运行时重要事件委托给app delegate
来处理。App delegate对象
App delegate
对象遵循UIApplicationDelegate
协议,响应app运行时重要事件(app启动、app内存不足、app终止、切换到另一个app、切回app),主要用于app在启动时初始化一些重要数据结构;例如,初始化UIWindow
,设置一些属性,为window添加rootViewController
。View controller对象
View Controller
有一个view
属性是view层次结构中的根view,你可以添加子view来构建复杂的view;controller有一些viewDidLoad
、viewWillAppear
等方法来管理view的生命周期;由于它继承UIResponder
,所有还会响应和处理用户事件。Documents和data model对象
data model对象主要用来存储数据。例如,饿了么app在搜索切换地址后,有历史记录搜索地址历史,当app下次启动时,读取和显示搜索地址历史。
document对象(继承UIDocument)用来管理一些或所有的data model对象。document对象并不是必须的,但提供一种方便的方式来分组属于单个文件或多个文件的数据。UIWindow对象
UIWindow
对象位于view层次结构中的最顶层,它充当一个基本容器而不显示内容,如果想显示内容,添加一个content view到window。
它也是继承UIResponder
,所以它也是会响应和处理用户事件。View、control、layer对象
View
对象可以通过addSubview和removeFromSuperview 等方法管理view的层次结构,使用layoutIfNeeded和setNeedsLayout等方法布局view的层次结构,当你发现系统提供view已经满足不了你想要的外观需求时,可以重写drawRect方法或通过layer属性来构造复杂的图形外观和动画。还有一点,UIView也是继承UIResponder,所以也能够处理用户事件。
Control
对象通常就是处理特定类型用户交互的View,常用的有button、switch、text field等。
除了使用View
和Control
来构建view层次结构来影响app外观之外,还可以使用Core Animation框架的Layer
对象来渲染view外观和构建复杂的动画。
MVC
iOS应用程序都遵循Model-View-Controller的架构,Model负责存储数据和处理业务逻辑,View负责显示数据和与用户交互,Controller是两者的中介,协调Model和View相互协作。
- 当View与用户交互产生事件时,使用target-action方式来处理
- 当View需要处理一些特殊UI逻辑或获取数据源时,通过delegate或data source方式交给Controller来处理
- Model不能直接与Controller通信,当Model有数据更新时,可以通过Notification或KVO (Key Value Observing)来通知Controller更新View
ios api
ios整体分为四层:
- Cocoa Touch层:提供一些基本服务:多线程、触摸输入推送等和关键框架:UIKit、WatchKit等
- Media层:提供了图形音频等技术
- Core Services层:提供基本服务,不提供界面:CloudKit、HealthKit等,应用购买,SQLite数据库和XML等技术
- Core OS层:提供硬件和网络相关的低级服务。
如何查看文档?
点击内置的函数名,点击问号就会出现该api的简介,如果想查看更详细的api信息就可以点击Open in Developer document 查看更多:
感想:
ios的开发是集成在一起的,无论创建文件,写代码,更改配置。而不像web项目一样,只有文件,所有的配置,也都是基于我们写的json等东西,想要改什么也直接修改文件,添加文件即可。 而在xcode里,比如我新加一个swift文件,我直接把文件复制到文件夹里是没有用的,必须经过xcode来添加这些文件(因为app 是一个bundle,而所有的路径管理也就是基于bundle这个对象)。其次ios修改了什么,想要看见效果都必须重新编译,没有所谓热更新之类的东西。
ios大概框架就是这个样子 以后再介绍学习了的更详细的内容。
参考
- iOS应用程序的生命周期
- 《ios指南》