空空叶博客 学习与开发博客

IOS开发旅程2

2018-09-10
kongkongye
ios

包含一些自我的想法,与熟悉的java语言的比较,项目的进化旅程等.

内存管理

对c语言来说,内存需要手动分配与释放,因此在objc里也类似. 在objc里,内存管理主要靠retain count(引用计数),在alloc,retain,copy时会加1,在release时会减1.

问题是什么?

内存管理主要有两个问题:

  1. 释放正在使用的对象: 程序崩溃
  2. 未释放不再使用的对象: 内存泄露

规则是什么?

内存管理的规则也很简单:

  1. 我们拥有创建的对象,不再使用时必须进行释放
  2. retain后不再使用时也必须release
  3. 不释放非自己拥有的对象

为了加深理解,举个例子,新建一个NSURLConnection连接,但是请求是异步返回的,那什么时候释放呢? 很简单,NSURLConnection对象用完就释放,它会在发送请求时将自己retain一次,请求返回时又会自动release一次. 因此你不用理它,管好自己就行,用完就释放.

ARC(Automic Reference Counting)

新版本的objc引入了ARC,管理内存的自动释放(对应的是MRC).

要注意的是这个是在编译时期(而非运行时期)自动在代码中插入合适的内存管理代码(类似插入retain,release,autorelease吧). 此外在运行期也会有一些优化.

项目文件结构

目标:

  1. 目录结构清晰
  2. 快速找到文件
  3. 减少依赖,增加可移植性

基本概念:

  • 主要的项目功能: 外层先按功能模块分,内层再按MVC分.
  • 工具类等功能: 单独的目录.
  • 模块内可以包含子模块,但建议层次不超过三级.

具体结构设计:

  • Class: 存放所有模块功能
  • Base: 存放基类
  • Vendor: 第三方(主要的第三方用cocoapods,小的放这里)
  • Framework: 类库
  • Resource: 存放资源
  • Support: 工具类,分类,宏定义,PCH文件等
  • Main: AppDelegate相关

XCode项目结构

  • Workspace: 就是工作空间,里面可以包含多个项目,为什么?比如这些项目间有关联.
    • Project: 项目的意思(这才是主体),包含构建一个或多个软件产品所需的所有文件,资源和信息
      • Target: 指定要构建的产品,并包含构建需要的文件说明.target之间可以互相独立或依赖.
  • Scheme: 定义可构建的Target以及构建时使用的构建信息

Project Navigator中,选择项目,右侧会展示Project Editor,这里可以看到所有的Target. 此外,可以看到产品信息和构建配置(Build Settings),其中构建配置内的大部分配置项还区分DebugRelease. Debug就是多输出一些调试信息,Release会进行代码优化.

关于Workspace的作用,可以拿Cocospods举例, 当使用Cocospods来管理第三方时,会自动新建一个跟原项目平行的Pods项目,里面放置第三方依赖. 原先打开的是一个名为app.xcodeproj项目,现在改为打开cocospods自动生成的名为app.xcworkspace工作空间, 工作空间里有原来的项目,与放置第三方依赖的Pods项目.

Target使用场景?

  1. 用来区分免费版与收费版,主体上功能差不多,一些地方有区别.
  2. 用来区分开发与生产环境
  3. 用来区分ios与ipad?

Scheme使用场景?

  1. 打测试包与正式包

XCode界面开发

Interface Builder

XCode中编辑界面的工具叫Interface Builder,关于这个工具: 之前是个独立软件,创建的文件是二进制格式nib. 后来集成到XCode内,为了方便版本控制,创建的文件是xib(xml文件格式), 在工程编译的时候再转为nib格式.

方式

界面开发主要有以下几种方式:

  1. 代码: 复杂的大项目推荐使用这种方式
    • 缺点:
    • 不直观,没法所见即所得,只能写完,然后运行才能看到效果
  2. xib
  3. storyboard(最新&官方推荐): 类似xib的集合,每个xib对应一个场景,可以设置场景关系(表现为一些连线)
    • IBOutlet: 就是引用了,让代码可以操控界面元素(它会解析为nothing,仅作为与界面相关的标记,如IBOutlet UILabel *title;)
    • IBAction: 比如点击按钮执行相应的方法(它会解析为void,同时也作为与界面相关的标记,如- (IBAction)ok:(id)sender;)
    • segue: 页面跳转方式(奇怪的名字)

    这是什么鬼?花了我好多时间研究. 首先它是名为UIStoryboardSegue的类,里面有id,来源UIViewController,目标UIViewController这几个字段,还有个perform方法.这就有些明了了,执行一个segue其实就是调用一下perform方法,然后在来源与目标ViewController之间做点操作而已,比如跳转,返回.

  • 缺点(继承了xib的所有缺点- -!):
    • 打开比较慢(因为多个场景同时展示)
    • 屏幕小时,编辑起来很挤
    • 多人编辑时,合并容易冲突: 因此实际工作中,一个storyboard最好只由一个人负责

吐槽: IBOutlet与IBAction的用法真奇葩,还不一样…两个都有标记的作用,标识着可以与界面产生交互(连线),但IBAction竟然代替了void的位置.

triggered segue/presenting segue

  • triggered segue: 就是用来触发segue的
  • presenting segue: 就是用来接受触发的

(明白这两种的区别,segue就很简单明了了)

自动/手动的segue

  • 自动型的segue: 比如从按钮直接拖线到另一个ViewController,action选择show,这样点击按钮就会跳转页面.自动型的没法加条件判断哦,要加可以使用手动的.
  • 手动型的segue: 在ViewController上右键,最上方的manual连线到另一个ViewController,action比如选择show.那么怎么触发这个segue呢?先选中这个,在Attributes inspector中设置identifier,然后比如点击按钮执行方法,在方法内使用[self performSegueWithIdentifier:@"id" sender:nil];即可手动执行segue了

segue类型

  1. modal(iphone&ipad): 最常用的,新的场景覆盖旧的,必须先关闭这个场景才能与上个场景交互
  2. push(iphone&ipad): 这种一般需要第一个界面是Navigation Controller,下一级使用那种右侧划入的方式
  3. custom(iphone&ipad): 自定义方式
  4. popover(ipad): 浮窗形式
  5. replace(ipad): 替换当前scene,经常用在ipad的特殊视图上(spit-view)
  6. unwind segue(或叫exit segue): 简单说就是返回,从页面A返回到页面B,连线时需要指定一个方法- (IBAction) unwindToThisViewController:(UIStoryboardSegue *) segue,这个方法写在B内(方法名随意). 执行这个segue时(如按钮或代码调用),就会执行这个方法并返回到B(执行方法在segue的perform前).

segue跳转代码

//根据 segue Identifier跳转界面
[self performSegueWithIdentifier:@"GotoTwo" sender:self];

//以modal 方式跳转
[self presentModalViewController:nil animated:YES];

// 以 modal跳转的返回方法
[self dismissModalViewControllerAnimated:YES];

//压进一个viewcontroller
[self.navigationController pushViewController:nil animated:YES];

//弹出一个viewcontroller  相当与返回上一个界面
[self.navigationController popViewControllerAnimated:YES];

比较如下

代码 xib storyboard  
复用性
批量处理

布局

  1. frame
  2. Autolayout(推荐)
    • 缺点:
    • 没有占位符,一些界面需要使用看不见的view来占位
    • 某些常见的界面布局难以表述,如等间距
    • 需要设置很多约束,比较繁琐
    • 需要根据约束去求解位置,某些场合下比较耗时

Size Class

按照View的尺寸大小分成几个类型,然后在xib/storyboard中根据类型设置不同约束.

设备宽高区分为CompactRegular,不区分为Any.

所有设备的Size Class都是预先固定定义好的,比如iphone6竖屏时wC hR(w表示width,h表示height,C表示Compact,R表示Regular),ipad不管竖屏还是横屏都是wR hR

Safe Area

用来避免内容被状态栏,导航栏,标签栏等覆盖.

IOS11前用的是topLayoutGuidebottomLayoutGuide,IOS11开始用safeAreaLayoutGuide代替.

推荐不要把内容放到Safe Area外.

First Responder & Exit

First Responder指任意对象在任意时间具有第一响应状态的代理对象. 比如某个输入框是First Responder时,按下按钮,给First Responder也就是输入框发送剪切的命令. 网上说实际用的不多.

Exit就是用来连线unwind segue的,看上面.

MVC

  • Controller直接引用View与Model
  • View与Controller通信:
    • 设置View对应的Action Target,如设置 UIButton 的 Touch up inside 的 Action Target
    • 设置View的delegate,如UIAlertViewDelegate
    • 设置View的data source,如UITableViewDataSource
  • Model与Controller通信:
    • Notification
    • KVO

其它问题

为什么字符串前要用@?

因为Objc与C语言兼容,如果不加,那么字符串会被编译器当作C语言的字符串. 那为什么不直接用C的字符串呢?因为NSString好用,方法多呗.

数字也是类似的道理.


下一篇 IOS开发旅程

目录