ios学习之路 —— 原理、生命周期、项目创建

为什么要学ios?

因为部门要开始进行rn开发了。

  • 为了能在开发前有更清晰的开发思路,以及在开发过程中能更好地定位问题和解决解决
  • 在阅读rn文档的时候,很多东西不理解,比如:
    1. 为什么一定要用style,而不能用css?:因为cssom是web特有的,native的基础组件都是class,而样式都是考给class设置值来实现的,所以也更不用说啥样式的继承啥了。
    2. 标签为什么没有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,声明长宽高等一堆属性,然后把它加入到视图中:
代码描述UI结构

他们并没有像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:
  • 挂起重新运行: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有一些viewDidLoadviewWillAppear等方法来管理view的生命周期;由于它继承UIResponder,所有还会响应和处理用户事件。

  • Documents和data model对象
    data model对象主要用来存储数据。例如,饿了么app在搜索切换地址后,有历史记录搜索地址历史,当app下次启动时,读取和显示搜索地址历史。
    document对象(继承UIDocument)用来管理一些或所有的data model对象。document对象并不是必须的,但提供一种方便的方式来分组属于单个文件或多个文件的数据。

  • UIWindow对象
    UIWindow对象位于view层次结构中的最顶层,它充当一个基本容器而不显示内容,如果想显示内容,添加一个content view到window。
    它也是继承UIResponder,所以它也是会响应和处理用户事件。

  • Viewcontrollayer对象
    View对象可以通过addSubview和removeFromSuperview 等方法管理view的层次结构,使用layoutIfNeeded和setNeedsLayout等方法布局view的层次结构,当你发现系统提供view已经满足不了你想要的外观需求时,可以重写drawRect方法或通过layer属性来构造复杂的图形外观和动画。还有一点,UIView也是继承UIResponder,所以也能够处理用户事件
    Control对象通常就是处理特定类型用户交互的View,常用的有button、switch、text field等。
    除了使用ViewControl来构建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大概框架就是这个样子 以后再介绍学习了的更详细的内容。

参考

推荐阅读更多精彩内容