原创:知识点总结性文章
创作不易,请珍惜,之后会持续更新,不断完善
个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的IOS成长历程,希望能与大家一起进步
温馨提示:由于不支持目录跳转,大家可通过command + F 输入目录标题后迅速寻找到你所需要的内容
目录
- 一、Xcode 开发环境
- 1、Project 属性设置
- 2、target 属性设置
- 3、info 属性设置
- 4、capabilities 属性设置
- 5、Resource Tag 属性设置
- 6、build setting 属性设置
- 7、build phase 属性设置
- 8、拖拽所需素材:便捷库
- 二、OC语言
- 1、简介
- 2、封装
- 3、继承
- 4、多态
- 5、常用枚举类型
- 三、UIView
- 1、视图元素
- 2、视图跳转
- 3、事件传递&视图响应
- 4、导入的框架文件
- 5、方法和属性
- 6、视图扩展
- 四、UIViewController 的生命周期
- 五、NSObject
- 1、NSObject 协议
- 2、NSObject 类的接口文件
- 六、Swift 语言和 OC 语言对比
- 1、联系
- 2、Swift 的优点
- 3、Swift 的缺点
- 4、细节区别
- 七、编码规范
一、Xcode 开发环境
Xcode Workspace
就如同工厂,Xcode Project
如同车间,每个车间可以独立于工厂来生产产品(project
可独立于workspace
存在),但是各个车间组合起来就需要工厂来组织(如果用了cocopods
,就需要用workspace
)。Xcode Target
是一条条的流水线,一条流水线上面只生产一种产品。Build Settings
是生产产品的秘方,如果是生产汽水,Build Settings
就是其中各个原料的配方。Xcode Scheme
是生产方案,包含了流水线生产,秘方,还包含生产完成之后的质检(test
)。
每个target
中的build setting
参数继承自 project
的build settings
, 一旦你在target
中修改任意settings
来重写project settings
,那么最终生效的 settings
参数以在 target
中设置的为准。 Project
可以包含多个target
, 但是在同一时刻,只会有一个 target
生效,可用 Xcode 的 scheme
来指定是哪一个 target
生效。
1、Project 属性设置
Deployment Target 部署配置
主要是对project
生成的App可以运行的最低版本进行配置,默认是当前Xcode
上API的最新版本,所以,在我们的项目中有需要对低版本适配的地方需要在这里设置。同样的,我们还可以在build setting
中对这一属性进行设置,两者是同步的。
Localizations 本地化
这里的功能主要是添加我们的App所支持的语言,通过上图最下面的红色圈内的【+】【-】按钮可以添加或删除不同的语种,并可以选择根据手机的设置进行不同语种的自适应。关于最下面的选择是否开启国际化,默认是开启的。
2、target 属性设置
发布信息
- Identify(标识符)栏:主要定义了一些和应用发布有关的标识属性
- Display Name(App应用显示名):安装到iOS手机或iPad上App的名称
- Bundle Identifier(包标识符):该应用的唯一
ID
,用来让AppStore
识别。在创建项目或者对象过程中Xcode
就自行创建了包标识符,一般情况下不要修改它 - Version(外部版本号):使用户能够看到的版本号
- Build(内部版本号):开发者自己看到的版本号,以区分内部测试版本
- Signing(签名):主要是进行证书管理,在真机调试或者打包时我们都需要进行签名认证才可以
部署信息
- Deployment Target(部署对象):用来设置支持的最低版本。这个和
project
的info
中的一个意思,并且,这两个的设置最好是一样,如果不一样,最后的App会以target
的设置为准 - Devices(设备):用来设置支持的设备,有iPhone、iPad和Universal三个选项。
- Main Interface(主界面):应用启动时预加载的主界面视图
- Device Orientation(设备方向):应用支持的方向。有
Portrait
、Upside Down
、Landscape Left
、Landscape Right
几种方向
应用图标
- Notification:通知时的图标。有应用相关的推送消息时需要显示本应用的图标则会显示这个尺寸的
- Spotlight:搜索图标。当在
Spotlight
中输入应用名,搜索结果中出现该应用时的图标就是这个尺寸的,还有设置里的图标也是这个尺寸的 - App:这就是正常的App图标,安装好之后在桌面显示的,或者分享时显示的应用也是这个尺寸的图标
- App Store:应用商店中的显示的图标
启动画面
- Luanch Image Source(启动图片):启动图片实际上定义了应用启动后的界面,一款App必须设定对应设备的启动图片,否则点开应用会是一片黑白
- Luanch Screen File(启动页面文件):
storyboard
文件,作用与Luanch Image
一样
框架
- Embedded Binaries(绑定二进制文件):用来连接二进制文件,一般在使用第三方SDK的时候使用。
- Linked Frameworks and Libraries(链接的框架和库):既可以是自带的框架,也可以是第三方框架,在
Build Phases
中也有类似的功能选项
3、info 属性设置
属性设置
- Localization native development region : 与本地化设置有关,为默认语言
- Executable file:程序安装包的名称
- Bundle identifier:APP唯一的标识,是根据公司的标识与项目名称自动生成的,在上传和测试的时候会用到
- InfoDictionary version:版本信息
- Bundle name:App安装后显示的名称
- Bundle OS Type code:用来标识软件包类型
- Bundle versions string:发布的版本字符串
- Bundle creator OS Type code:创建者的标识
- Bundle version:应用程序版本号
- Application requires iPhone environment:用于指示程序包是否只能运行在IOS系统上,默认为YES
- Launch screen interface file base name:启动界面的文件名称
- Main storyboard file base name:默认情况下程序的主入口
- Supported interface orientations:设置程序默认支持的方向
权限设置
- 麦克风权限:
Privacy - Microphone Usage Description
是否允许使用你的麦克风? - 相机权限:
Privacy - Camera Usage Description
是否允许使用你的相机? - 相册权限:
Privacy - Photo Library Usage Description
是否允许访问你的媒体资料库? - 通讯录权限:
Privacy - Contacts Usage Description
是否允许访问你的通讯录? - 蓝牙权限:
Privacy - Bluetooth Peripheral Usage Description
是否许允使用蓝牙? - 语音转文字权限:
Privacy - Speech Recognition Usage Description
是否允许使用语音识别? - 日历权限:
Privacy - Calendars Usage Description
是否允许使用日历? - 定位权限:
Privacy - Location When In Use Usage Description
我们需要通过您的地理位置信息获取您周边的相关数据 - 定位权限:
Privacy - Location Always Usage Description
我们需要通过您的地理位置信息获取您周边的相关数据
4、capabilities 属性设置
性能设置开关选择,例如推送通知、云存储、游戏中心、后台模式等。
5、Resource Tag 属性设置
主要是为项目中的资源进行添加tag
分类,方便我们对其加载顺序和加载时机进行选择和设置,即实现在需要的时候才加载资源。
app资源的延迟加载
app有一些只在特定情景下使用的资源,当应用可能要进入这些场景时,会请求这些资源。例如,在一个有很多关卡的游戏中,用户只需要当前关卡和下一关卡的资源。
不常用资源的远程存储
app有一些很少使用的资源,当需要这些资源时会去请求它们。例如,当app第一次打开时会展示一个教程,而这个教程之后就可能不会在用到。app在第一次启动时请求教程的资源,这之后只在需要展示教程或者添加了新功能才去请求该资源。
应用内购买资源的远程存储
app提供包含额外资源的应用内购买。app会在启动完成后请求已购买模块的资源。例如,用户在一个键盘app内购买了SuperGeeky
表情包。应用程序会在启动完成后请求表情包的资源。
第一次启动时必需资源的加载
app有一些资源只在第一次启动时需要,之后的启动不再需要。例如,app有一个只在第一次启动时展示的教程。
6、build setting 属性设置
Resolved列
最终确定的编译方式,无法自己设定,其结果是根据其右边三栏的选择结果以及优先级顺序来确定最后编译时采用的编译方式。在图的第二行选项卡中选择combined
选项,可以直接地看到只有该栏的最后结果。
带Target图标列
target
的build setting
配置的编译选项,可自定义。其优先级最高,一旦进行设置,则最后的编译方式以该栏的结果为准。
带Project图标列
project
的build setting
配置的编译选项,可自定义,这一栏的结果与project
中build setting
选项卡中的结果是一致的,修改其中一个地方,另一处也会自动修改。其优先级介于target
和default
之间,当target
没有设置编译选项,而该栏进行了设置时,则最后的编译方式以该栏为准。
iOS Default列
在创建项目时系统自带的默认编译选项,无法修改。优先级最低,只有当其他两栏都没有设置选项时,最后的编译方式才会以该栏为准。
7、build phase 属性设置
配置编译器在不同编译阶段的参数,包括编译所需的资源文件(代码、配置以及各种资源文件)
Target Dependencies Target 对象依赖阶段
某些Target
可能依赖某个Target
输出的值,需要在这里设置依赖。依赖于其他target
的输出的时候,在编译时系统会自动先编译被依赖的target
,得到输出值,再编译当前target
。(比如应用扩展、插件等等),这个阶段是无法被修改的。
Compile Sources 源文件编译阶段
指定有哪些源代码被编译,可以通过红框中的【+】【-】按钮进行添加或删除资源来控制编译的代码文件。并且可以通过修改阶段的Compiler Flags
(编译器标识)来为每个单独文件设置其编译器标识,比如优化设置等等。
Link Binary With Libraries 链接二进制库阶段
指编译过程中会引用哪些库文件,我们同样可以通过【+】【-】按钮进行添加或删除编译所引用的库文件。
Copy Bundle Resources 复制资源文件阶段
指生成的product
的.app
内将包含哪些资源文件,同样可以通过红框中的【+】【-】按钮进行添加或删除资源来控制编译的资源文件。该阶段定义了对象中的资源文件,包括应用程序、图标、界面构造器、视频、模板等等。这些资源都会被复制到安装包的Contents/Resources
文件夹下。
8、拖拽所需素材:便捷库
当你需要创建 UI 界面,却想不起视图写法时;当你需要使用某个 Swift 语法结构,却忘记正确拼写时;当你需要添加图片,却记不清图片名称时,都可以使用便捷库来快速添加以上内容。快捷库的开启按钮为 Xcode 顶边栏右侧的「+」按钮。
点击后,你会发现便捷库中提供五个选项,分别是「视图Views
,修改器 Modifiers
,代码段 Snippets
,媒体库 Media
,颜色板 Color
」。其中视图和修改器属于界面搭建的范畴。代码段包含 Swift
中常用的各种语法结构。媒体库包含图片等文件。颜色板则包含Assets
文件夹中自定义的所有颜色。
便捷库中所有内容均可以直接选中并拖拽至 Xcode 的编辑器面板中使用。比如下面的例子,我们可以从便捷库中拖拽添加一张图片后,再拖拽允许图片自动调整大小的代码。
有时你可能会觉得系统默认的便捷库内容并不完全满足你的需求,那么如何将自定义内容添加进便捷库中呢?往便捷库的不同选项卡中添加内容的方式稍有不同。你在 Assets
里添加的图片和颜色等内容会自动显示在快捷库中,无需进行任何额外操作。
若你希望将代码段显示在便捷库中,可以使用鼠标选择想要加入的代码区域,并右键选择「Create Code Snippet
」,效果如下图。若你希望将某些部分做成占位符,可以将占位符部分的文字用如下格式书写 <#占位符#>
,中间的占位符部分便会自动完成转化。
二、OC语言
1、简介
OC语言是C 编程语言的超集,提供面向对象的功能和动态运行时。虽然消息发送同函数调用相比确实慢一点,但却有面向对象的动态绑定优点。
面向对象的三大特性是面向对象语言的精华所在。面向对象是基于万物皆对象这个哲学观点。抽象化指的是尽可能地不考虑相关细节,只关注对象的核心和本质。类就是舍弃了每个具体对象的各种细节的模版。把一个对象抽象成类,具体上就是把一个对象的静态特征和动态特征抽象成相应的属性和方法,也就是把一类事物的算法和数据结构封装在一个类之中。程序就是多个对象和互相之间的通信组成的。用类创建对象的过程叫作实例化(instantiation ),不同对象之间可以共享该类中的方法,差异就在于具体值的不同。
面向对象具有封装性,继承性,多态性。封装隐蔽了对象内部不需要暴露给外人的细节,使得内部细节的变动跟外界不相关,只单纯依靠提供的接口进行通信,封装性降低了编程的复杂度。通过继承,使得新建一个类变得更加容易,一个类从父类那里获得其方法和属性的工作就交给了编译器。多态使得不同的类所产生的对象能够对相同的消息作出不同的反应,这极大地提高了代码的通用性。总之言而,面向对象的三大特性大大提高了程序的重用性和可维护性。
2、三大特性
什么是封装
- 在程序上,隐藏对象的属性和方法实现细节,控制在程序中属性的读和修改的访问级别,仅对外公开接口
- 将数据和功能相结合,形成一个有机的整体,形成“类”,其中数据和函数都是类的成员
封装的好处
- 过滤不合理的值
- 屏蔽内部的赋值过程
- 让外部不必关注内部实现细节
3、继承
- 什么是继承:通过继承,子类可以拥有父类中所有的成员变量和方法
- 重写:子类重新实现父类中某个方法,覆盖父类以前的做法
作用
- 不改变原来模型的基础上,拓展方法
- 建立了类与类之间的联系
- 抽取了公共代码
使用场合
- 子类重写父类方法时,想保留父类方法的一些行为
- 当两个类拥有相同的属性和方法时,就可以将相同的东西抽取出到父类中
注意
- 调用某个方法时,优先去当前类中寻找,如果找不到,再去父类中寻找
- oc语言是单继承,父类必须声明在子类前面
- 子类不能拥有和父类相同的成员变量
- 缺点是耦合性太强,删除父类后,子类就不能够继续使用
4、多态
父类类型变量不能够直接调用子类特有的方法(编译过程会有警告)。必须强转为子类类型便后后,才能够直接调用子类特有的方法。
首先从多态的定义来说:用一个父类的指针指向子类的对象,在函数(方法)调用的时候可以调用到正确版本的函数(方法)。
使用多态的条件:1.子类必须重写父类的方法。2.父类指针指向子类对象。
多态的使用:1. 父类的引用指向子类的对象,发送消息,调用的是子类对象的方法。2. 父类的引用指向本类的对象,发送消息,调用本类的方法。
在多态下,父类的引用可以指向子类的引用,当编译的时候,编译器无法确定指向的对象是什么类型,所有编译器会将引用当做父类类型引用编译检查。
在调用方法时,发现确实是子类对象,为子类类型创建空间。例如:Person *p=[Student alloc] init]
编译时,会把Student
类型当成Person
类型编译。[p play]
运行时,调用的是Student
类型的对象。在OC中,调用方法是,会检测对象的真实类型,称为动态绑定。
态的好处:1.提供动态绑定特性,减少不必要的程序冗余。在方法中,把父类当成参数,使该方法具备调用所有子类同样方法的能力,不比为每个子类都写个方法。2. 多态的出现提高了程序的扩展性和后期可维护型。
// 父类的指针指向子类的对象
Tree *t1 = [[Osier alloc] init];
[t1 grow];
Tree *t2 = [[PineTree alloc] init];
[t2 grow];
输出结果为:
柳树在春天发芽
松树四季常青
三、UIView
1、视图元素
- 控件:继承自
UIControl
类,能够响应用户高级事件 - 窗口:应用只有一个
UIWindow
对象,它是所有子视图的“根"容器 - 容器视图:
UIScrollView
的子类有UITextView
、UITableView
和UICollectionView
,在内容超出屏幕时,它们可以提供水平或垂直滚动条 - 显示视图:包括
UIImageView
、UILabel
、UIProgressView
和UIActivityindicatorView
- 文本和Web视图:包括
UITextview
和WKWebView
,WKWebView
是能够加载和显示HTML
代码的视图 - 导航视图:包括
UITabBar
和UINavigationBar
属性声明
@property (nonatomic, strong, readonly) UILabel *title;
@property (nonatomic, strong) UIPickerView *pickerView;
@property (nonatomic, strong) UIDatePicker *datePicker;
@property (nonatomic, strong) UIScrollView *scrollView;
@property (nonatomic, strong) UIPageControl *pageControl;
继承图
2、视图跳转
- 故事板:本质上是一个
XML
文件,可以用来描述应用中有哪些界面,界面中有哪些视图元素,界面的布局、事件处理,以及界面之间是如何导航(或跳转)的 - 场景 (scene) 和过渡 (segue):一个场景中包含一个视图控制器,视图控制器通过管理视图来显示界面。过渡定义了场景之间的导航(或跳转)方式
- Show Segue:在当前视图上展示视图,如果当前控制器是导航控制器,那么视图的显示会采用树形结构导航模式;如果不是导航控制器,那么视图显示会采用模态 (
Modal
) 导航模式。 - Show Detail Segue:当采用
UISplitViewController
控制器时, 在Detail
视图中显示视图。 如果在其他导航控制器中使用这个过渡,那么它和ShowSegue
的效果是一样的 - Modal Segue:模态导航模式
- Popover Segue:Pad设备上呈现浮动窗口
3、事件传递&视图响应
UIView
为其提供内容以及负责处理触摸等事件,参与响应链,CALayer
负责显示内容contents
,这是单一执行原则。
响应者对象就是可以响应事件并对事件作出处理的对象。在iOS中UIResponder
类定义了响应者对象的所有方法。UIApplication
、UIWindow
、UIViewController
、UIView
以及UIKit
中继承自UIView
的控件都间接或直接继承自UIResponder
类,这些类都可以当做响应者。
响应者链表示一系列响应者对象组成的事件传递的链条。当确定了第一响应者后,事件交由第一响应者处理,如果第一响应者不处理事件沿着响应者链传递,交给下一个响应者。一般来说,第一响应者是UIView
对象或者UIView
的子类对象,当其被触摸后事件交由它处理,如果它不处理,事件就会交给它的UIViewController
处理(如果存在),然后是它的superview
父视图对象,以此类推,直到顶层视图。如果顶层视图不处理则交给UIWindow
对象处理,再到UIApplication
对象。如果整个响应者链都不响应这个事件则该事件被丢弃。
第一响应者,如操作UITextField来控制键盘的现隐藏
- (BOOL)canBecomeFirstResponder
- (BOOL)becomeFirstResponder
- (BOOL)canResignFirstResponder
- (BOOL)resignFirstResponder;
- (BOOL)isFirstResponder
视图传递流程
视图响应流程
4、导入的框架文件
#import
#import
#import
#import
#import
#import
#import
#import
#import
#import
5、常用枚举类型
视图动画曲线 UIViewAnimationCurve
/** 动画的曲线枚举 */
typedef NS_ENUM(NSInteger, UIViewAnimationCurve) {
UIViewAnimationCurveEaseInOut, //!< 慢进慢出(默认值)
UIViewAnimationCurveEaseIn, //!< 慢进
UIViewAnimationCurveEaseOut, //!< 慢出
UIViewAnimationCurveLinear, //!< 匀速
};
视图内容填充模式 UIViewContentMode
//!< UIView内容填充模式.
typedef NS_ENUM(NSInteger, UIViewContentMode) {
UIViewContentModeScaleToFill, //!< 缩放内容到合适比例大小
UIViewContentModeScaleAspectFit, //!< 缩放内容到合适的大小,边界多余部分透明
UIViewContentModeScaleAspectFill, //!< 缩放内容填充到指定大小,边界多余的部分省略
UIViewContentModeRedraw, //!< 重绘视图边界 (需调用 -setNeedsDisplay)
UIViewContentModeCenter, //!< 视图保持等比缩放
UIViewContentModeTop, //!< 视图顶部对齐
UIViewContentModeBottom, //!< 视图底部对齐
UIViewContentModeLeft, //!< 视图左侧对齐
UIViewContentModeRight, //!< 视图右侧对齐
UIViewContentModeTopLeft, //!< 视图左上角对齐
UIViewContentModeTopRight, //!< 视图右上角对齐
UIViewContentModeBottomLeft, //!< 视图左下角对齐
UIViewContentModeBottomRight, //!< 视图右下角对齐
};
视图动画过渡效果 UIViewAnimationTransition
/** UIView动画过渡效果 */
typedef NS_ENUM(NSInteger, UIViewAnimationTransition) {
UIViewAnimationTransitionNone, //!< 无效果
UIViewAnimationTransitionFlipFromLeft, //!< 沿视图垂直中心轴左到右移动
UIViewAnimationTransitionFlipFromRight, //!< 沿视图垂直中心轴右到左移动
UIViewAnimationTransitionCurlUp, //!< 由底部向上卷起
UIViewAnimationTransitionCurlDown, //!< 由顶部向下展开
};
视图自动调整大小方式 UIViewAutoresizing
/** 自动调整大小方式 */
typedef NS_OPTIONS(NSUInteger, UIViewAutoresizing) {
UIViewAutoresizingNone = 0, //!< 不自动调整
UIViewAutoresizingFlexibleLeftMargin = 1 << 0,//!< 自动调整与superView左边的距离,保证与superView右边的距离不变
UIViewAutoresizingFlexibleWidth = 1 << 1,//!< 自动调整自己的宽度,保证与superView左边和右边的距离不变
UIViewAutoresizingFlexibleRightMargin = 1 << 2,//!< 自动调整与superView的右边距离,保证与superView左边的距离不变
UIViewAutoresizingFlexibleTopMargin = 1 << 3,//!< 自动调整与superView顶部的距离,保证与superView底部的距离不变
UIViewAutoresizingFlexibleHeight = 1 << 4,//!< 自动调整自己的高度,保证与superView顶部和底部的距离不变
UIViewAutoresizingFlexibleBottomMargin = 1 << 5 //!< 自动调整与superView底部的距离,也就是说,与superView顶部的距离不变
};
视图的动画选项 UIViewAnimationOptions
/** UIView动画选项 */
typedef NS_OPTIONS(NSUInteger, UIViewAnimationOptions) {
UIViewAnimationOptionLayoutSubviews = 1 << 0, //!< 动画过程中保证子视图跟随运动
UIViewAnimationOptionAllowUserInteraction = 1 << 1, //!< 动画过程中允许用户交互
UIViewAnimationOptionBeginFromCurrentState = 1 << 2, //!< 所有视图从当前状态开始运行
UIViewAnimationOptionRepeat = 1 << 3, //!< 重复运行动画
UIViewAnimationOptionAutoreverse = 1 << 4, //!< 动画运行到结束点后仍然以动画方式回到初始点
UIViewAnimationOptionOverrideInheritedDuration = 1 << 5, //!< 忽略嵌套动画时间设置
UIViewAnimationOptionOverrideInheritedCurve = 1 << 6, //!< 忽略嵌套动画速度设置
UIViewAnimationOptionAllowAnimatedContent = 1 << 7, //!< 动画过程中重绘视图(注意仅仅适用于转场动画)
UIViewAnimationOptionShowHideTransitionViews = 1 << 8, //!< 视图切换时直接隐藏旧视图、显示新视图,而不是将旧视图从父视图移除(仅仅适用于转场动画)
UIViewAnimationOptionOverrideInheritedOptions = 1 << 9, //!< 不继承父动画设置或动画类型
UIViewAnimationOptionCurveEaseInOut = 0 << 16, //!< 动画先缓慢,然后逐渐加速
UIViewAnimationOptionCurveEaseIn = 1 << 16, //!< 动画逐渐变慢
UIViewAnimationOptionCurveEaseOut = 2 << 16, //!< 动画逐渐加速
UIViewAnimationOptionCurveLinear = 3 << 16, //!< 动画匀速执行,默认值
UIViewAnimationOptionTransitionNone = 0 << 20, //!< 没有转场动画效果
UIViewAnimationOptionTransitionFlipFromLeft = 1 << 20, //!< 从左侧翻转效果
UIViewAnimationOptionTransitionFlipFromRight = 2 << 20, //!< 从右侧翻转效果
UIViewAnimationOptionTransitionCurlUp = 3 << 20, //!< 向后翻页的动画过渡效果
UIViewAnimationOptionTransitionCurlDown = 4 << 20, //!< 向前翻页的动画过渡效果
UIViewAnimationOptionTransitionCrossDissolve = 5 << 20, //!< 旧视图溶解消失显示下一个新视图的效果
UIViewAnimationOptionTransitionFlipFromTop = 6 << 20, //!< 从上方翻转效果
UIViewAnimationOptionTransitionFlipFromBottom = 7 << 20, //!< 从底部翻转效果
UIViewAnimationOptionPreferredFramesPerSecondDefault = 0 << 24, //!< 默认的帧每秒
UIViewAnimationOptionPreferredFramesPerSecond60 = 3 << 24, //!< 60帧每秒的帧速率
UIViewAnimationOptionPreferredFramesPerSecond30 = 7 << 24, //!< 30帧每秒的帧速率
} NS_ENUM_AVAILABLE_IOS(4_0);
视图关键帧动画选项 UIViewKeyframeAnimationOptions
typedef NS_OPTIONS(NSUInteger, UIViewKeyframeAnimationOptions) {
UIViewKeyframeAnimationOptionLayoutSubviews = UIViewAnimationOptionLayoutSubviews, //!< 动画过程中保证子视图跟随运动
UIViewKeyframeAnimationOptionAllowUserInteraction = UIViewAnimationOptionAllowUserInteraction, //!< 动画过程中允许用户交互
UIViewKeyframeAnimationOptionBeginFromCurrentState = UIViewAnimationOptionBeginFromCurrentState, //!< 所有视图从当前状态开始运行
UIViewKeyframeAnimationOptionRepeat = UIViewAnimationOptionRepeat, //!< 重复运行动画
UIViewKeyframeAnimationOptionAutoreverse = UIViewAnimationOptionAutoreverse, //!< 动画运行到结束点后仍然以动画方式回到初始点
UIViewKeyframeAnimationOptionOverrideInheritedDuration = UIViewAnimationOptionOverrideInheritedDuration, //!< 忽略嵌套动画时间设置
UIViewKeyframeAnimationOptionOverrideInheritedOptions = UIViewAnimationOptionOverrideInheritedOptions, //!< 不继承父动画设置或动画类型
UIViewKeyframeAnimationOptionCalculationModeLinear = 0 << 10, //!< 连续运算模式 默认
UIViewKeyframeAnimationOptionCalculationModeDiscrete = 1 << 10, //!< 离散运算模式
UIViewKeyframeAnimationOptionCalculationModePaced = 2 << 10, //!< 均匀执行运算模式
UIViewKeyframeAnimationOptionCalculationModeCubic = 3 << 10, //!< 平滑运算模式
UIViewKeyframeAnimationOptionCalculationModeCubicPaced = 4 << 10 //!< 平滑均匀运算模式
} NS_ENUM_AVAILABLE_IOS(7_0);
视图的系统动画 UISystemAnimation
typedef NS_ENUM(NSUInteger, UISystemAnimation) {
UISystemAnimationDelete, //!< 系统删除动画
} NS_ENUM_AVAILABLE_IOS(7_0);
视图的外观色调调整模式 UIViewTintAdjustmentMode
typedef NS_ENUM(NSInteger, UIViewTintAdjustmentMode) {
UIViewTintAdjustmentModeAutomatic, //!< 自动的,与父视图相同
UIViewTintAdjustmentModeNormal, //!< 未经修改的
UIViewTintAdjustmentModeDimmed, //!< 饱和、暗淡的原始色
} NS_ENUM_AVAILABLE_IOS(7_0);
语义内容属性 UISemanticContentAttribute
typedef NS_ENUM(NSInteger, UISemanticContentAttribute) {
UISemanticContentAttributeUnspecified = 0, //!< 未指定,默认值
UISemanticContentAttributePlayback, //!< 打开/ RW / FF等播放控制按钮
UISemanticContentAttributeSpatial, //!< 控制导致某种形式的定向改变UI中,如分段控制文本对齐方式或在游戏中方向键
UISemanticContentAttributeForceLeftToRight, //!< 视图总是从左向右布局
UISemanticContentAttributeForceRightToLeft //!< 视图总是从右向左布局
} NS_ENUM_AVAILABLE_IOS(9_0);
布局约束的轴 UILayoutConstraintAxis
typedef NS_ENUM(NSInteger, UILayoutConstraintAxis) {
UILayoutConstraintAxisHorizontal = 0, //!< 水平约束
UILayoutConstraintAxisVertical = 1 //!< 竖直约束
};
坐标空间协议 UICoordinateSpace
@protocol UICoordinateSpace
/** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point toCoordinateSpace:(id )coordinateSpace NS_AVAILABLE_IOS(8_0);
/** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point fromCoordinateSpace:(id )coordinateSpace NS_AVAILABLE_IOS(8_0);
/** 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect */
- (CGRect)convertRect:(CGRect)rect toCoordinateSpace:(id )coordinateSpace NS_AVAILABLE_IOS(8_0);
/** 将rect从view中转换到当前视图中,返回在当前视图中的rect */
- (CGRect)convertRect:(CGRect)rect fromCoordinateSpace:(id )coordinateSpace NS_AVAILABLE_IOS(8_0);
/** 获取bounds */
@property (readonly, nonatomic) CGRect bounds NS_AVAILABLE_IOS(8_0);
@end
5、方法和属性
@class UIBezierPath, UIEvent, UIWindow, UIViewController, UIColor, UIGestureRecognizer, UIMotionEffect, CALayer, UILayoutGuide;
@interface UIView : UIResponder
/** 返回主layer所使用的类 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) Class layerClass;
#else
+ (Class)layerClass;
#endif
@end
类方法 2个
/** 获取视图的方向 */
+ (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)attribute NS_AVAILABLE_IOS(9_0);
/** 获取相对于指定视图的界面方向 */
+ (UIUserInterfaceLayoutDirection)userInterfaceLayoutDirectionForSemanticContentAttribute:(UISemanticContentAttribute)semanticContentAttribute relativeToLayoutDirection:(UIUserInterfaceLayoutDirection)layoutDirection NS_AVAILABLE_IOS(10_0);
初始化方法 2个
/** 通过Frame初始化UI对象 */
- (instancetype)initWithFrame:(CGRect)frame NS_DESIGNATED_INITIALIZER;
/** 用于xib初始化 */
- (nullable instancetype)initWithCoder:(NSCoder *)aDecoder NS_DESIGNATED_INITIALIZER;
属性 8个
/** 设置用户交互,默认YES允许用户交互 */
@property(nonatomic,getter=isUserInteractionEnabled) BOOL userInteractionEnabled;
/** 控件标记(父控件可以通过tag找到对应的子控件),默认为0 */
@property(nonatomic) NSInteger tag;
/** 视图图层(可以用来设置圆角效果/阴影效果) */
@property(nonatomic,readonly,strong) CALayer *layer;
/** 返回是否可以成为焦点, 默认NO */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic,readonly) BOOL canBecomeFocused NS_AVAILABLE_IOS(9_0);
#else
- (BOOL)canBecomeFocused NS_AVAILABLE_IOS(9_0);
#endif
/** 是否可以被聚焦 */
@property (readonly, nonatomic, getter=isFocused) BOOL focused NS_AVAILABLE_IOS(9_0);
/** 左右滑动翻转效果 */
@property (nonatomic) UISemanticContentAttribute semanticContentAttribute NS_AVAILABLE_IOS(9_0);
/** 返回即时内容的布局的方向 */
@property (readonly, nonatomic) UIUserInterfaceLayoutDirection effectiveUserInterfaceLayoutDirection NS_AVAILABLE_IOS(10_0);
6、视图扩展
视图几何相关的扩展 UIView(UIViewGeometry)
@interface UIView(UIViewGeometry)
/** 位置和尺寸(以父控件的左上角为坐标原点(0, 0)) */
@property(nonatomic) CGRect frame;
/** 位置和尺寸(以自己的左上角为坐标原点(0, 0)) */
@property(nonatomic) CGRect bounds;
/** 中心点(以父控件的左上角为坐标原点(0, 0)) */
@property(nonatomic) CGPoint center;
/** 变形属性(平移\缩放\旋转) */
@property(nonatomic) CGAffineTransform transform;
/** 视图内容的缩放比例 */
@property(nonatomic) CGFloat contentScaleFactor NS_AVAILABLE_IOS(4_0);
/** 是否支持多点触摸,默认NO */
@property(nonatomic,getter=isMultipleTouchEnabled) BOOL multipleTouchEnabled __TVOS_PROHIBITED;
/** 是否独占整个Touch事件,默认NO */
@property(nonatomic,getter=isExclusiveTouch) BOOL exclusiveTouch __TVOS_PROHIBITED;
/** 在指定点上点击测试指定事件 */
- (nullable UIView *)hitTest:(CGPoint)point withEvent:(nullable UIEvent *)event;
/** 判断当前的点击或者触摸事件的点是否在当前的view中,默认返回YES */
- (BOOL)pointInside:(CGPoint)point withEvent:(nullable UIEvent *)event;
/** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point toView:(nullable UIView *)view;
/** 将像素point由point所在视图转换到目标视图view中,返回在目标视图view中的像素值 */
- (CGPoint)convertPoint:(CGPoint)point fromView:(nullable UIView *)view;
/** 将rect由rect所在视图转换到目标视图view中,返回在目标视图view中的rect */
- (CGRect)convertRect:(CGRect)rect toView:(nullable UIView *)view;
/** 将rect从view中转换到当前视图中,返回在当前视图中的rect */
- (CGRect)convertRect:(CGRect)rect fromView:(nullable UIView *)view;
/** 自动调整子视图尺寸,默认YES则会根据autoresizingMask属性自动调整子视图尺寸 */
@property(nonatomic) BOOL autoresizesSubviews;
/** 自动调整子视图与父视图的位置,默认UIViewAutoresizingNone */
@property(nonatomic) UIViewAutoresizing autoresizingMask;
/** 返回“最佳”大小适合给定的大小 */
- (CGSize)sizeThatFits:(CGSize)size;
/** 调整为刚好合适子视图大小 */
- (void)sizeToFit;
@end
视图层次结构相关的扩展 UIView(UIViewHierarchy)
@interface UIView(UIViewHierarchy)
/** 获取父视图 */
@property(nullable, nonatomic,readonly) UIView *superview;
/** 获取所有子视图 */
@property(nonatomic,readonly,copy) NSArray<__kindof UIView *> *subviews;
/** 获取视图所在的Window */
@property(nullable, nonatomic,readonly) UIWindow *window;
/** 从父视图中移除控件 */
- (void)removeFromSuperview;
/** 插入子视图(将子视图插入到subviews数组中index这个位置) */
- (void)insertSubview:(UIView *)view atIndex:(NSInteger)index;
/** 交换subviews数组中所存放子视图的位置 */
- (void)exchangeSubviewAtIndex:(NSInteger)index1 withSubviewAtIndex:(NSInteger)index2;
/** 添加子视图(新添加的视图在subviews数组的后面, 显示在最上面) */
- (void)addSubview:(UIView *)view;
/** 插入子视图(将子视图插到siblingSubview之下) */
- (void)insertSubview:(UIView *)view belowSubview:(UIView *)siblingSubview;
/** 插入子视图(将子视图插到siblingSubview之上) */
- (void)insertSubview:(UIView *)view aboveSubview:(UIView *)siblingSubview;
/** 将子视图拉到最上面来显示 */
- (void)bringSubviewToFront:(UIView *)view;
/** 将子视图拉到最下面来显示 */
- (void)sendSubviewToBack:(UIView *)view;
系统自动调用(留给子类去实现)
/** 添加子视图完成后调用 */
- (void)didAddSubview:(UIView *)subview;
/** 将要移除自视图时调用 */
- (void)willRemoveSubview:(UIView *)subview;
/** 将要移动到新父视图时调用 */
- (void)willMoveToSuperview:(nullable UIView *)newSuperview;
/** 移动到新父视图完成后调用 */
- (void)didMoveToSuperview;
/** 将要移动到新Window时调用 */
- (void)willMoveToWindow:(nullable UIWindow *)newWindow;
/** 移动到新Window完成后调用 */
- (void)didMoveToWindow;
/** 判断view是否为子类 */
- (BOOL)isDescendantOfView:(UIView *)view;
/** 通过tag获得对应的子视图 */
- (nullable __kindof UIView *)viewWithTag:(NSInteger)tag;
/** 对现在有布局有调整更改后,使用这个方法进行更新 */
- (void)setNeedsLayout;
/** 强制进行更新layout */
- (void)layoutIfNeeded;
/** 控件的frame发生改变的时候就会调用,一般在这里重写布局子控件的位置和尺寸 */
- (void)layoutSubviews;
/** 设置view之间的间距,该属性只对autolayout布局有效 */
@property (nonatomic) UIEdgeInsets layoutMargins NS_AVAILABLE_IOS(8_0);
/** 是否将当前视图的间距和父视图相同,默认是NO */
@property (nonatomic) BOOL preservesSuperviewLayoutMargins NS_AVAILABLE_IOS(8_0);
/** 改变view的layoutMargins这个属性时,会触发这个方法 */
- (void)layoutMarginsDidChange NS_AVAILABLE_IOS(8_0);
/** 视图间距引导 */
@property(readonly,strong) UILayoutGuide *layoutMarginsGuide NS_AVAILABLE_IOS(9_0);
/** 获取此区域的内的布局引导 */
@property (nonatomic, readonly, strong) UILayoutGuide *readableContentGuide NS_AVAILABLE_IOS(9_0);
@end
视图外观渲染相关的扩展 UIView (UIViewRendering)
@interface UIView(UIViewRendering)
/** 重写drawRect方法,在可以这里进行绘图操作。*/
- (void)drawRect:(CGRect)rect;
/** 标记整个视图的边界矩形需要重绘, 调用这个方法会自动调用drawRect方法 */
- (void)setNeedsDisplay;
/** 标记在指定区域内的视图的边界需要重绘, 调用这个方法会自动调用drawRect方法 */
- (void)setNeedsDisplayInRect:(CGRect)rect;
/** 是否裁剪超出Bounds范围的子控件,默认NO */
@property(nonatomic) BOOL clipsToBounds;
/** 设置背景颜色,默认nil */
@property(nullable, nonatomic,copy) UIColor *backgroundColor UI_APPEARANCE_SELECTOR;
/** 设置透明度(范围0.0~1.0),默认1.0 */
@property(nonatomic) CGFloat alpha;
/** 设置是否不透明,默认YES不透明 */
@property(nonatomic,getter=isOpaque) BOOL opaque;
/** 视图重绘前是否先清理以前的内容,默认YES */
@property(nonatomic) BOOL clearsContextBeforeDrawing;
/** 设置是否隐藏,默认NO不隐藏 */
@property(nonatomic,getter=isHidden) BOOL hidden;
/** 内容显示的模式,默认UIViewContentModeScaleToFill */
@property(nonatomic) UIViewContentMode contentMode;
/** 拉伸属性,如图片拉伸 */
@property(nonatomic) CGRect contentStretch NS_DEPRECATED_IOS(3_0,6_0) __TVOS_PROHIBITED;
/** 蒙板view */
@property(nullable, nonatomic,strong) UIView *maskView NS_AVAILABLE_IOS(8_0);
/** 改变应用程序的外观的颜色。默认为nil */
@property(null_resettable, nonatomic, strong) UIColor *tintColor NS_AVAILABLE_IOS(7_0);
/** 可以使tintColor变暗,因此整个视图层次变暗 */
@property(nonatomic) UIViewTintAdjustmentMode tintAdjustmentMode NS_AVAILABLE_IOS(7_0);
/** 覆盖这个方法的目的是为了当tintColor改变的时候自定义一些行为 */
- (void)tintColorDidChange NS_AVAILABLE_IOS(7_0);
@end
视图动画相关的扩展 UIView (UIViewAnimation)
@interface UIView(UIViewAnimation)
/** 开始动画 */
+ (void)beginAnimations:(nullable NSString *)animationID context:(nullable void *)context;
/** 提交动画 */
+ (void)commitAnimations;
/** 设置动画代理, 默认nil */
+ (void)setAnimationDelegate:(nullable id)delegate;
/** 动画将要开始时执行方法(必须要先设置动画代理), 默认NULL */
+ (void)setAnimationWillStartSelector:(nullable SEL)selector;
/** 动画已结束时执行方法(必须要先设置动画代理), 默认NULL */
+ (void)setAnimationDidStopSelector:(nullable SEL)selector;
/** 设置动画时长, 默认0.2秒 */
+ (void)setAnimationDuration:(NSTimeInterval)duration;
/** 动画延迟执行时间, 默认0.0秒 */
+ (void)setAnimationDelay:(NSTimeInterval)delay;
/** 设置在动画块内部动画属性改变的开始时间, 默认now ([NSDate date]) */
+ (void)setAnimationStartDate:(NSDate *)startDate;
/** 设置动画曲线, 默认UIViewAnimationCurveEaseInOut */
+ (void)setAnimationCurve:(UIViewAnimationCurve)curve;
/** 动画的重复播放次数, 默认0 */
+ (void)setAnimationRepeatCount:(float)repeatCount;
/** 设置是否自定翻转当前的动画效果, 默认NO */
+ (void)setAnimationRepeatAutoreverses:(BOOL)repeatAutoreverses;
/** 设置动画从当前状态开始播放, 默认NO */
+ (void)setAnimationBeginsFromCurrentState:(BOOL)fromCurrentState;
/** 在动画块中为视图设置过渡动画 */
+ (void)setAnimationTransition:(UIViewAnimationTransition)transition forView:(UIView *)view cache:(BOOL)cache;
/** 设置是否激活动画 */
+ (void)setAnimationsEnabled:(BOOL)enabled;
/** 返回一个布尔值表示动画是否结束 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) BOOL areAnimationsEnabled;
#else
+ (BOOL)areAnimationsEnabled;
#endif
/** 先检查动画当前是否启用,然后禁止动画,执行block内的方法,最后重新启用动画,而且这个方法不会阻塞基于CoreAnimation的动画 */
+ (void)performWithoutAnimation:(void (NS_NOESCAPE ^)(void))actionsWithoutAnimation NS_AVAILABLE_IOS(7_0);
/** 当前动画的持续时间 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) NSTimeInterval inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#else
+ (NSTimeInterval)inheritedAnimationDuration NS_AVAILABLE_IOS(9_0);
#endif
@end
视图用block快速定义动画的扩展 UIView (UIViewAnimationWithBlocks)
@interface UIView(UIViewAnimationWithBlocks)
/** 用于对一个或多个视图的改变的持续时间、延时、选项动画完成时的操作 */
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
/** 用于对一个或多个视图的改变的持续时间、选项动画完成时的操作,默认:delay = 0.0, options = 0 */
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
/** 用于对一个或多个视图的改变的持续时间内动画完成时的操作,默认:delay = 0.0, options = 0, completion = NULL */
+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations NS_AVAILABLE_IOS(4_0);
/** 使用与物理弹簧运动相对应的定时曲线执行视图动画 */
+ (void)animateWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay usingSpringWithDamping:(CGFloat)dampingRatio initialSpringVelocity:(CGFloat)velocity options:(UIViewAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
/** 为指定的容器视图创建转换动画 */
+ (void)transitionWithView:(UIView *)view duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0);
/** 使用给定的参数在指定视图之间创建转换动画 */
+ (void)transitionFromView:(UIView *)fromView toView:(UIView *)toView duration:(NSTimeInterval)duration options:(UIViewAnimationOptions)options completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(4_0); // toView added to fromView.superview, fromView removed from its superview
/** 在一个或多个视图上执行指定的系统提供的动画,以及定义的可选并行动画 */
+ (void)performSystemAnimation:(UISystemAnimation)animation onViews:(NSArray<__kindof UIView *> *)views options:(UIViewAnimationOptions)options animations:(void (^ __nullable)(void))parallelAnimations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
@end
视图关键帧动画相关的扩展 UIView (UIViewKeyframeAnimations)
/** UIView的关键帧动画 */
@interface UIView (UIViewKeyframeAnimations)
/** 创建一个动画块对象,可用于为当前视图设置基于关键帧的动画 */
+ (void)animateKeyframesWithDuration:(NSTimeInterval)duration delay:(NSTimeInterval)delay options:(UIViewKeyframeAnimationOptions)options animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion NS_AVAILABLE_IOS(7_0);
/** 添加指定开始时间、持续时间的关键帧动画(起始和持续时间是0.0和1.0之间的值) */
+ (void)addKeyframeWithRelativeStartTime:(double)frameStartTime relativeDuration:(double)frameDuration animations:(void (^)(void))animations NS_AVAILABLE_IOS(7_0);
@end
视图上手势相关的扩展 UIView (UIViewGestureRecognizers)
@interface UIView (UIViewGestureRecognizers)
/** 当前视图所附加的所有手势识别器 */
@property(nullable, nonatomic,copy) NSArray<__kindof UIGestureRecognizer *> *gestureRecognizers NS_AVAILABLE_IOS(3_2);
/** 添加一个手势识别器 */
- (void)addGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);
/** 移除一个手势识别器 */
- (void)removeGestureRecognizer:(UIGestureRecognizer*)gestureRecognizer NS_AVAILABLE_IOS(3_2);
/** 开始一个手势识别器 */
- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer NS_AVAILABLE_IOS(6_0);
@end
视图上运动效果相关的扩展 UIView(UIViewMotionEffects)
@interface UIView (UIViewMotionEffects)
/** 添加运动效果,当倾斜设备时视图稍微改变其位置 */
- (void)addMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);
/** 移除运动效果 */
- (void)removeMotionEffect:(UIMotionEffect *)effect NS_AVAILABLE_IOS(7_0);
/** 所有添加的运动效果 */
@property (copy, nonatomic) NSArray<__kindof UIMotionEffect *> *motionEffects NS_AVAILABLE_IOS(7_0);
@end
视图上安装约束相关的扩展 UIView (UIConstraintBasedLayoutInstallingConstraints)
@interface UIView (UIConstraintBasedLayoutInstallingConstraints)
/** 获取所有约束 */
@property(nonatomic,readonly) NSArray<__kindof NSLayoutConstraint *> *constraints NS_AVAILABLE_IOS(6_0);
/** 添加一个约束 */
- (void)addConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
/** 添加多个约束 */
- (void)addConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);
/** 移除一个约束 */
- (void)removeConstraint:(NSLayoutConstraint *)constraint NS_AVAILABLE_IOS(6_0);
/** 移除多个约束 */
- (void)removeConstraints:(NSArray<__kindof NSLayoutConstraint *> *)constraints NS_AVAILABLE_IOS(6_0);
@end
视图上约束相关的扩展 UIView (UIConstraintBasedLayoutCoreMethods)
@interface UIView (UIConstraintBasedLayoutCoreMethods)
/** 更新视图和其子视图的约束 */
- (void)updateConstraintsIfNeeded NS_AVAILABLE_IOS(6_0);
/** 为视图更新约束,可以重写这个方法来设置当前view局部的布局约束 */
- (void)updateConstraints NS_AVAILABLE_IOS(6_0) NS_REQUIRES_SUPER;
/** 视图的约束是否需要更新 */
- (BOOL)needsUpdateConstraints NS_AVAILABLE_IOS(6_0);
/** 设置视图的约束需要更新,调用这个方法,系统会调用updateConstraints去更新布局 */
- (void)setNeedsUpdateConstraints NS_AVAILABLE_IOS(6_0);
@end
视图上约束共存相关的扩展 UIView (UIConstraintBasedCompatibility)
@interface UIView (UIConstraintBasedCompatibility)
/** 是否启用自动布局约束,默认YES. IB默认是NO */
@property(nonatomic) BOOL translatesAutoresizingMaskIntoConstraints NS_AVAILABLE_IOS(6_0);
/** 是否使用约束布局 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(class, nonatomic, readonly) BOOL requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);
#else
+ (BOOL)requiresConstraintBasedLayout NS_AVAILABLE_IOS(6_0);
#endif
@end
视图约束布局图层相关的扩展 UIView (UIConstraintBasedLayoutLayering)
@interface UIView (UIConstraintBasedLayoutLayering)
/** 返回给定框架的视图的对齐矩阵 */
- (CGRect)alignmentRectForFrame:(CGRect)frame NS_AVAILABLE_IOS(6_0);
/** 返回给定对齐矩形的视图的frame */
- (CGRect)frameForAlignmentRect:(CGRect)alignmentRect NS_AVAILABLE_IOS(6_0);
/** 返回从视图的frame上定义的对齐矩阵的边框 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) UIEdgeInsets alignmentRectInsets NS_AVAILABLE_IOS(6_0);
#else
- (UIEdgeInsets)alignmentRectInsets NS_AVAILABLE_IOS(6_0);
#endif
/** 返回满足基线约束条件的视图 */
- (UIView *)viewForBaselineLayout NS_DEPRECATED_IOS(6_0, 9_0, "Override -viewForFirstBaselineLayout or -viewForLastBaselineLayout as appropriate, instead") __TVOS_PROHIBITED;
/** 返回用于满足第一基线约束的视图 */
@property(readonly,strong) UIView *viewForFirstBaselineLayout NS_AVAILABLE_IOS(9_0);
/** 返回用于满足上次基线约束的视图 */
@property(readonly,strong) UIView *viewForLastBaselineLayout NS_AVAILABLE_IOS(9_0);
UIKIT_EXTERN const CGFloat UIViewNoIntrinsicMetric NS_AVAILABLE_IOS(6_0); // -1
/** 返回接收对象的原本大小 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) CGSize intrinsicContentSize NS_AVAILABLE_IOS(6_0);
#else
- (CGSize)intrinsicContentSize NS_AVAILABLE_IOS(6_0);
#endif
/** 废除视图原本内容的size */
- (void)invalidateIntrinsicContentSize NS_AVAILABLE_IOS(6_0);
/** 设置当视图要变大时,视图的压缩改变方式,返回一个优先权(确定view有多大的优先级阻止自己变大) */
- (UILayoutPriority)contentHuggingPriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
/** 设置放先权 */
- (void)setContentHuggingPriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
/** 设置当视图要变小时,视图的压缩改变方式,是水平缩小还是垂直缩小,并返回一个优先权(确定有多大的优先级阻止自己变小) */
- (UILayoutPriority)contentCompressionResistancePriorityForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
/** 设置优先权 */
- (void)setContentCompressionResistancePriority:(UILayoutPriority)priority forAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
@end
视图约束适应尺寸相关的扩展 UIView (UIConstraintBasedLayoutFittingSize)
@interface UIView (UIConstraintBasedLayoutFittingSize)
/** 返回满足持有约束的视图的size */
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize NS_AVAILABLE_IOS(6_0);
/** 返回满足它所包含的约束的视图的大小 */
- (CGSize)systemLayoutSizeFittingSize:(CGSize)targetSize withHorizontalFittingPriority:(UILayoutPriority)horizontalFittingPriority verticalFittingPriority:(UILayoutPriority)verticalFittingPriority NS_AVAILABLE_IOS(8_0);
@end
视图布局引导相关的扩展 UIView (UILayoutGuideSupport)
@interface UIView (UILayoutGuideSupport)
/** 此视图拥有布局向导对象的数组 */
@property(nonatomic,readonly,copy) NSArray<__kindof UILayoutGuide *> *layoutGuides NS_AVAILABLE_IOS(9_0);
/** 向视图中添加布局向导 */
- (void)addLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);
/** 向视图中添加布局向导 */
- (void)removeLayoutGuide:(UILayoutGuide *)layoutGuide NS_AVAILABLE_IOS(9_0);
@end
@class NSLayoutXAxisAnchor,NSLayoutYAxisAnchor,NSLayoutDimension;
@interface UIView (UIViewLayoutConstraintCreation)
/** 布局视图的前缘框的布局锚点 */
@property(readonly, strong) NSLayoutXAxisAnchor *leadingAnchor NS_AVAILABLE_IOS(9_0);
/** 布局视图的后缘边框的布局锚点 */
@property(readonly, strong) NSLayoutXAxisAnchor *trailingAnchor NS_AVAILABLE_IOS(9_0);
/** 布局视图的左边框的布局锚点 */
@property(readonly, strong) NSLayoutXAxisAnchor *leftAnchor NS_AVAILABLE_IOS(9_0);
/** 布局视图的右边框的布局锚点 */
@property(readonly, strong) NSLayoutXAxisAnchor *rightAnchor NS_AVAILABLE_IOS(9_0);
/** 布局视图的顶边框的布局锚点 */
@property(readonly, strong) NSLayoutYAxisAnchor *topAnchor NS_AVAILABLE_IOS(9_0);
/** 布局视图的底边框的布局锚点 */
@property(readonly, strong) NSLayoutYAxisAnchor *bottomAnchor NS_AVAILABLE_IOS(9_0);
/** 布局视图的宽度 */
@property(readonly, strong) NSLayoutDimension *widthAnchor NS_AVAILABLE_IOS(9_0);
/** 布局视图的高度 */
@property(readonly, strong) NSLayoutDimension *heightAnchor NS_AVAILABLE_IOS(9_0);
/** 布局视图的水平中心轴 */
@property(readonly, strong) NSLayoutXAxisAnchor *centerXAnchor NS_AVAILABLE_IOS(9_0);
/** 布局视图的垂直中心轴 */
@property(readonly, strong) NSLayoutYAxisAnchor *centerYAnchor NS_AVAILABLE_IOS(9_0);
/** 一个代表对视图中的文本的最高线基线布置锚 */
@property(readonly, strong) NSLayoutYAxisAnchor *firstBaselineAnchor NS_AVAILABLE_IOS(9_0);
/** 一个代表对视图中的文本的最低线基线布置锚 */
@property(readonly, strong) NSLayoutYAxisAnchor *lastBaselineAnchor NS_AVAILABLE_IOS(9_0);
@end
视图约束布局调试相关的扩展 UIView (UIConstraintBasedLayoutDebugging)
@interface UIView (UIConstraintBasedLayoutDebugging)
/** 获得实体在不同方向上所有的布局约束 */
- (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(6_0);
/** 可以知道当前视图的布局是否会有歧义 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);
#else
- (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(6_0);
#endif
/** 这个方法会随机改变视图的layout到另外一个有效的layout。这样我们就可以很清楚的看到哪一个layout导致了整体的布局约束出现了错误,或者我们应该增加更多的布局约束 */
- (void)exerciseAmbiguityInLayout NS_AVAILABLE_IOS(6_0);
@end
/** 约束调试,只在DEBUG环境下被调用 */
@interface UILayoutGuide (UIConstraintBasedLayoutDebugging)
/** 获得实体在不同方向上所有的布局约束 */
- (NSArray<__kindof NSLayoutConstraint *> *)constraintsAffectingLayoutForAxis:(UILayoutConstraintAxis)axis NS_AVAILABLE_IOS(10_0);
/** 可以知道当前视图的布局是否会有歧义 */
#if UIKIT_DEFINE_AS_PROPERTIES
@property(nonatomic, readonly) BOOL hasAmbiguousLayout NS_AVAILABLE_IOS(10_0);
#else
- (BOOL)hasAmbiguousLayout NS_AVAILABLE_IOS(10_0);
#endif
@end
视图状态保存恢复相关的扩展 UIView (UIStateRestoration)
#pragma mark - View状态保存恢复
@interface UIView (UIStateRestoration)
/** 标示是否支持保存,恢复视图状态信息 */
@property (nullable, nonatomic, copy) NSString *restorationIdentifier NS_AVAILABLE_IOS(6_0);
/** 保存视图状态相关的信息 */
- (void) encodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
/** 恢复和保持视图状态相关信息 */
- (void) decodeRestorableStateWithCoder:(NSCoder *)coder NS_AVAILABLE_IOS(6_0);
@end
视图快照相关的扩展 UIView(UISnapshotting)
#pragma mark - View快照
@interface UIView (UISnapshotting)
/** 将当前显示的view截取成一个新的view */
- (nullable UIView *)snapshotViewAfterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
/** 缩放一个view默认是从中心点进行缩放的 */
- (nullable UIView *)resizableSnapshotViewFromRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates withCapInsets:(UIEdgeInsets)capInsets NS_AVAILABLE_IOS(7_0);
/** 屏幕快照 */
- (BOOL)drawViewHierarchyInRect:(CGRect)rect afterScreenUpdates:(BOOL)afterUpdates NS_AVAILABLE_IOS(7_0);
@end
四、UIViewController 的生命周期
alloc// 创建对象,分配空间
init (initWithNibName)// 初始化对象,初始化数据
initWithCoder:(NSCoder *)aDecoder// 如果使用storyboard或者xib
loadView// 加载view
viewDidLoad// 载入完成,只会在APP刚开始加载的时候调用一次,所以只能用来做初始设置
viewWillAppear// 需要对数据做更新
viewDidAppear// 视图已在屏幕上渲染完成
viewWillDisappear// 被移除覆盖时进行善后的处理,按了Home键之后,APP本身仍是挂起时候的view,不调用
viewDidDisappear// 对已经消失、覆盖、隐藏了的视图做一些其他操作
dealloc// 视图被销毁,此处需要对你在init和viewDidLoad中创建的对象进行释放
viewWillLayoutSubviews// 多次调用布局
viewDidLayoutSubviews
五、NSObject
字母缩写
- f:
function
函数 - p:
parameter
参数 - m:
method
方法 - c:
class
类 - v:
variable
变量
NSObject.h 的结构
#include
#include
@class NSString, NSMethodSignature, NSInvocation;
1、NSObject 协议
@protocol NSObject
/** 判断两个对象是否相等, 如相等返回YES, 否则返回NO */
- (BOOL)isEqual:(id)object;
/** 获取对象hash值, 两对象相等hash值也相等 */
@property (readonly) NSUInteger hash;
/** 获取对象的父类 */
@property (readonly) Class superclass;
/** 获取当前对象的类 */
- (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");
/** 获取当前对象 */
- (instancetype)self;
/** 发送指定的消息给对象, 返回消息执行结果(相当于方法调用) */
- (id)performSelector:(SEL)aSelector;
/** 发送带一个参数的消息给对象, 返回消息执行结果(相当于方法调用) */
- (id)performSelector:(SEL)aSelector withObject:(id)object;
/** 发送带两个参数的消息给对象, 返回消息执行结果(相当于方法调用) */
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
/** 判断对象是否继承NSObject */
- (BOOL)isProxy;
/** 判断对象是否是给定类或给定类子类的实例 */
- (BOOL)isKindOfClass:(Class)aClass;
/** 判断对象是否是给定类的实例 */
- (BOOL)isMemberOfClass:(Class)aClass;
/** 判断对象是否遵从给定的协议 */
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
/** 判断对象是否能够调用给定的方法 */
- (BOOL)respondsToSelector:(SEL)aSelector;
/** 对象引用计数加1, 在MRC下使用 */
- (instancetype)retain OBJC_ARC_UNAVAILABLE;
/** 对象引用计数减1, 在MRC下使用 */
- (oneway void)release OBJC_ARC_UNAVAILABLE;
/** 对象引用计数以推迟方式自动减1, 在MRC下使用 */
- (instancetype)autorelease OBJC_ARC_UNAVAILABLE;
/** 获取对象引用计数, 在MRC下使用 */
- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;
/** 获取对象存储空间, 在MRC下使用 */
- (struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;
/** 获取对象描述信息 */
@property (readonly, copy) NSString *description;
@optional
/** 获取对象在调试器中的描述信息 */
@property (readonly, copy) NSString *debugDescription;
@end
2、NSObject 类的接口文件
@interface NSObject
/** 运行时加载类或分类调用该方法, 每个类只会调用一次 */
+ (void)load;
/** 类实例化使用前需要先初始化, 一个类调用一次, 如果子类没有实现该方法则会调用父类方法 */
+ (void)initialize;
/** 初始化对象 */
- (instancetype)init;
/** 为新对象分配内存空间并初始化, 等于[[NSObject alloc] init] */
+ (instancetype)new;
/** 为新对象分配内存空间, 参数传nil */
+ (instancetype)allocWithZone:(struct _NSZone *)zone;
/** 为新对象分配内存空间 */
+ (instancetype)alloc;
/** 释放对象, 当对象的引用计数为0时会调用此方法 */
- (void)dealloc;
/** 垃圾回收器调用此方法前处理它所使用的内存。 */
- (void)finalize;
/** 复制为不可变对象 */
- (id)copy;
/** 复制为可变对象 */
- (id)mutableCopy;
/** 在指定的内存空间上复制为不可变对象, 在MRC下使用 */
+ (id)copyWithZone:(struct _NSZone *)zone;
/** 在指定的内存空间上复制为可变对象, 在MRC下使用 */
+ (id)mutableCopyWithZone:(struct _NSZone *)zone;
/** 判断类是否能够调用给定的方法 */
+ (BOOL)instancesRespondToSelector:(SEL)aSelector;
/** 判断类是否遵从给定的协议 */
+ (BOOL)conformsToProtocol:(Protocol *)protocol;
/** 获取指向方法实现IMP的指针 */
- (IMP)methodForSelector:(SEL)aSelector;
/** 获取指向实例方法实现IMP的指针 */
+ (IMP)instanceMethodForSelector:(SEL)aSelector;
/** 找不到函数实现的将调用此方法抛出异常 */
- (void)doesNotRecognizeSelector:(SEL)aSelector;
/** 返回消息被第一个转发的对象, 对象没有找到SEL的IML时就会执行调用该方法 */
- (id)forwardingTargetForSelector:(SEL)aSelector;
/** methodSignatureForSelector:返回不为nil则调用该方法, 可以重写该方法将SEL转发给另一个对象 */
- (void)forwardInvocation:(NSInvocation *)anInvocation;
/** 获取方法签名, 对象没有找到SEL的IML时就会执行调用该方法, 可以重写该方法抛出一个函数的签名,再由forwardInvocation:去执行 */
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector;
/** 获取实例方法签名 */
+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)aSelector;
/** 允许弱引用标量, 对于所有allowsWeakReference方法返回NO的类都绝对不能使用__weak修饰符 */
- (BOOL)allowsWeakReference;
/** 保留弱引用变量, 在使用__weak修饰符的变量时, 当被赋值对象的retainWeakReference方法返回NO的情况下, 该变量将使用“nil” */
- (BOOL)retainWeakReference;
/** 判断是否是另一个类的子类 */
+ (BOOL)isSubclassOfClass:(Class)aClass;
/** 动态解析一个类方法 */
+ (BOOL)resolveClassMethod:(SEL)sel;
/** 动态解析一个实例方法, 对象没有找到SEL的IML时就会执行调用该方法, 可以重写该方法给对象添加所需的SEL */
+ (BOOL)resolveInstanceMethod:(SEL)sel;
/** 获取对象hash值, 两对象相等hash值也相等*/
+ (NSUInteger)hash;
/** 获取对象的父类 */
+ (Class)superclass;
/** 获取类 */
+ (Class)class;
/** 获取对象描述信息 */
+ (NSString *)description;
/** 获取对象在调试器中的描述信息 */
+ (NSString *)debugDescription;
@end
六、Swift 语言和 OC 语言对比
现阶段Swift能完全取代Objective-C吗?
Apple内部一直在用Objective-C
来做一些Framework
的开发,底层也不可能用Swift
实现。
1、联系
-
Swift
和Objective-C
共用一套运行时环境 -
Swift
的类型可以桥接到Objective-C
,反之亦然 - OC出现过的绝大多数概念,比如引用计数、ARC、属性、协议、接口、初始化、扩展类、命名参数、
block
等,在Swift
中继续有效(最多换个术语),当然Swift也多出了一些新兴概念,比如泛型、元组
2、Swift 的优点
- swift是类型安全的语言,注重安全,OC注重灵活
- swift注重面向协议编程、函数式编程,OC注重面向对象编程
- swift注重值类型,OC注重指针和引用
- swift是静态类型语言(类型的检查是在编译阶段做的,如
C++
、Java
),OC是动态类型语言(类型的检查是在运行时做的,如JavaScript
和Python
) - swift容易阅读,文件结构和大部分语法简易化,只有
.swift
文件,结尾不需要分号 - swift中的可选类型,用于所有数据类型,而不仅仅局限于类。相比于OC中的
nil
更加安全和简明 - swift中的泛型类型更加方便和通用,而非OC中只能为集合类型添加泛型
- swift中各种方便快捷的高阶函数(函数式编程)(Swift的数组支持三个高阶函数:
map
,filter
和reduce
,以及map
的扩展flatMap
) - swift新增了两种权限,细化权限。
open > public > internal(默认)> fileprivate > private
- swift中独有的元组类型(
tuples
),把多个值组合成复合值。元组内的值可以是任何类型,并不要求是相同类型的 - swift支持函数式编程,Objc本身是不支持的,需要通过引入
ReactiveCocoa
这个库才可支持函数式编程
3、Swift的缺点
- 版本不稳定
- 对于不支持Swift的一些第三方类库,如果非得使用,只能混合编程,利用桥接文件实现
4、细节区别
- 在 swift 中没有了
main.m
,@UIApplicationMain
是程序入口 - swift不分
.h
和.m
文件 ,一个类只有.swift
一个文件,所以整体的文件数量比起OC有一定减少 - swift句尾不需要分号 ,除非你想在一行中写三行代码就加分号隔开
- 在 swift 中,一个类就是用一对
{ }
括起的,没有@implementation
和@end
- swift数据类型都会自动判断 , 只区分变量
var
和常量let
- 强制类型转换格式不同:
OC强转:(int)a
,Swift强转:Int(a)
- 关于
BOOL
类型更加严格 ,Swift不再是OC的非0就是真,而是true
才是真,false
才是假 - swift的循环语句中必须加
{}
就算只有一行代码也必须要加 - swift的
switch
语句后面可以跟各种数据类型了 ,如Int
、字符串都行,并且里面不用写break
-
if
后的括号可以省略:if a>b {}
,而OC里if
后面必须写括号。 - 打印变量时可以
print("(value)")
,不用像OC那样记很多%@
,%d
等。 - swift的
Any
可以代表任何类型的值,无论是类、枚举、结构体还是任何其他Swift类型,这个对应OC中的id
类型 - 在OC中的
alloc / init
对应()
- 在OC中的
alloc / initWithXXX
对应(XXX: )
- 在 OC 中的类函数调用,在
swift
中,直接使用.
- 在 swift 中,绝大多数可以省略
self.
,建议一般不写,可以提高对语境的理解(闭包时会体会到) - 在 OC 中的枚举类型使用
UIButtonTypeContactAdd
,而 swift 中分开了,操作热键:回车-> 向右 ->.
- swift 中,枚举类型的前缀可以省略,如:
.ContactAdd
- swift中的范围运算符更灵活。
a...b
表示[a,b]
包括a和b
。 (如3...5 就是范围取3,4,5)。a.. 表示
[a,b)
包括a,不包括b
。 (如3...5 就是范围取3,4)。常见的如for循环:for i in 0...9{}
七、编码规范
原创:知识点总结性文章
创作不易,请珍惜,之后会持续更新,不断完善
个人比较喜欢做笔记和写总结,毕竟好记性不如烂笔头哈哈,这些文章记录了我的IOS成长历程,希望能与大家一起进步
温馨提示:由于不支持目录跳转,大家可通过command + F 输入目录标题后迅速寻找到你所需要的内容
目录
- 编码规范
价值
- 统一团队书写习惯,为效率工具提供了技术模版,奠定了自动化实践的基石
- 根除阅读障碍,有效降低CR和轮岗成本
- 增强了团队和谐
变量
- 只能以字母、数字、下划线、$组成;
- 不能以数字开头;
- 遵循小驼峰命名方式;
- 不能与C语言的关键字重名;
new
copy
- 区分大小写;
- 先声明后使用;
- 不能重复定义同名变量;
@interface UCARSomeBusinessService () {
// 声明一些私有变量,但不推荐;推荐使用私有属性方式声明
NSString *title;
NSInteger count;
}
属性
// 公共属性应该声明在类头文件(.h)中
@interface UCARSomeBusinessService : UCARBaseBusinessService
@property (nonatomic, strong) UCARSomeProperty *someProperty;
@property (nonatomic, copy) NSString *otherProperty;
@end
// 私有属性应该声明在类实现文件(.m)的延展(匿名的类目)中
@interface UCARSomeBusinessService ()
@property (nonatomic, strong) UCARSomeProperty *someProperty;
@property (nonatomic, copy) NSString *otherProperty;
@end
常量
// 常量格式:常量首选内联字符串字面量或数字,因为常量可以轻易重用并且可以快速改变而不需要查找和替换;
// 常量应该声明为 static 常量而不是 #define ,除非非常明确地要当做宏来使用
static NSString *const viewControllerTitle = @"派单页面";
static const CGFloat cellHeight = 66.66;
枚举
// 枚举格式:关键字、空格、换行、单行注释(居右)按如下书写
typedef NS_ENUM(NSInteger, UCAROrderState) {
UCAROrderState_Dispatching = 0, // 派单中
UCAROrderState_Dispatched = 1, // 派单成功
UCAROrderState_Arrival = 2, // 司机已到达
UCAROrderState_InService = 3 // 服务中
};
// 当用到位掩码时,使用 NS_OPTIONS 宏
typedef NS_OPTIONS(NSUInteger, UCARAdCategory) {
UCARAdCategoryAutos = 1 << 0, // Autos
UCARAdCategoryJobs = 1 << 1, // Jobs
UCARAdCategoryRealState = 1 << 2, // RealState
UCARAdCategoryTechnology = 1 << 3 // Technology
};
Method
方法定义要遵循单一原则,方法签名不要超过100字符,方法体不宜过长,方法名较短时应单行书写
方法格式:“+/-”+空格+(返回值类型)+方法名+空格+{+换行
- (void)produceView {
// Do something
}
- (UIView *)produceViewWithModel:(UCARModel *)model {
// Do something
}
+ (UIView *)produceViewWithTag:(NSInteger)tag {
// Do something
}
@protocol
@interface
Delegate
尽量使用can
、should
、will
、did
表明回调意愿&
时机;
属性&
方法添加注释:.h
文件中的注释,必须使用 Command + /
生成的模版进行编写
属性&
方法过多时,视情况使用 “换行” 分组
// import分组次序:Frameworks、Services、UI
#import
@protocol UCARSomeBusinessDelegate
@interface UCARSomeBusinessService : UCARBusinessService
@required
/**
* 属性说明
* @note 额外说明的注意项,说明一些需要注意的地方,没有可取消此项。
*/
@property (nonatomic, copy) NSString *otherProperty;
@property (nonatomic, strong) UCARSomeProperty *someProperty;
/**
* 方法说明
* @param object 一个参数
* @return 一个返回值
* @note 额外说明的注意项,说明一些需要注意的地方,没有可取消此项。
*/
- (void)shouldUpdateViewWithModel:(UCARSomeViewModel *)model;
- (void)shouldUpdateViewWithError:(NSError *)error;
- (void)willChangeDataSource;
- (void)didChangeDataSource;
@end
@implementation
@class UCARAnyProperty;
#pragma mark - 常量
#pragma mark - 枚举
@interface UCARSomeBusinessService ()
#pragma mark - 私有属性
@end
@implementation UCARSomeBusinessService
//方法列表使用pragma分组,并遵守如下次序, 且# pragma mark - 与上下各添加一个空行
#pragma mark - Life cycle
- (void)someMethod:(UCARSomeModel *)model {
// Do something
// Block 书写格式
[UIView animateWithDuration:0.3 animations:^{
// Do something
} completion:^(BOOL finished) {
// Do something
}];
}
#pragma mark - Custom Delegates
#pragma mark - Public Methods
#pragma mark - Private Methods
#pragma mark - Getters and Setters
@end
UIViewController
#pragma mark - Life cycle
- (instancetype)init {
}
- (void)viewDidLoad {
}
- (void)viewWillAppear:(BOOL)animated {
}
- (void)viewDidAppear:(BOOL)animated {
}
- (void)didReceiveMemoryWarning {
}
- (void)viewWillDisappear:(BOOL)animated {
}
- (void)viewDidDisappear:(BOOL)animated {
}
- (void)dealloc {
}
#pragma mark - Events
#pragma mark - UITextFieldDelegate
#pragma mark - UITableViewDataSource
#pragma mark - UITableViewDelegate
#pragma mark - UIOtherComponentDelegate
#pragma mark - Custom Delegates
#pragma mark - Public Methods
#pragma mark - Private Methods
#pragma mark - Getters and Setters
UIView
AutoLayout
、Frame
禁止混合使用,只能选择一种方式!!!
#pragma mark - Life cycle
- (instancetype)init {
}
- (instancetype)initWithFrame:(CGRect)frame {
}
- (void)updateConstraints {
}
- (void)layoutSubviews {
}
+ (BOOL)requiresConstraintBasedLayout {
return YES;
}
- (void)dealloc {
}
#pragma mark - Events
#pragma mark - UIOtherComponentDelegate
#pragma mark - Custom Delegates
#pragma mark - Public Methods
#pragma mark - Private Methods
#pragma mark - Getters and Setters
Snippets
IF/ELSE/SWITCH/FOR/WHILE
语句格式:关键字+空格+(条件)+空格+{+换行
IF
语句(如果IF
语句不是方法体第一行,与上面的代码之间添加一行空行,如果ELSE
语句不是最后一行,与下面代码之间加一行空行)
if (condition1) {
// Do something1
} else if (condition2) {
// Do something2
} else {
// Do anything
}
不推荐
if (condition) return value;
if (condition)
return value;
SWITCH
语句
switch (condition) {
case 1:
// ...
break;
case 2: {
// ...
// Multi-line example using braces
break;
}
default:
// ...
break;
}
FOR
语句
for (NSObject *object in list) {
// Do something
}
for (int i = 0; i < N; i++) {
// Do something
}
WHILE
语句
while (condition) {
// Do something
}
do {
// Do something
} while (condition)
方法命名
通用命名、属性方法命名、Delegate
方法命名、集合方法命名、方法参数命名、私有方法命名
通用命名
1、使用小驼峰命名规则
2、对于表示对象采取的操作的方法,使用动词开始
- (void)invokeWithTarget:(id)target;
- (void)selectTabViewItem:(NSTabViewItem *)tabViewItem;
3、所有参数之前使用关键字
- (void)sendAction:(SEL)aSelector toObject:(id)anObject forAllCells:(BOOL)flag; ✅
- (void)sendAction:(SEL)aSelector :(id)anObject :(BOOL)flag; ❌
4、在参数之前创建单词描述参数
- (id)viewWithTag:(NSInteger)aTag; ✅
- (id)taggedView:(int)aTag; ❌
5、在创建比继承方法更具体的方法时,在现有方法的末尾添加新关键字
- (id)initWithFrame:(CGRect)frameRect; 父类
- (id)initWithFrame:(NSRect)frameRect mode:(int)aMode cellClass:(Class)factoryId numberOfRows:(int)rowsHigh numberOfColumns:(int)colsWide; 子类
6、不要使用“and”
来链接作为接收者属性的关键字
- (int)runModalForDirectory:(NSString *)path file:(NSString *)name types:(NSArray *)fileTypes; ✅
- (int)runModalForDirectory:(NSString *)path andFile:(NSString *)name andTypes:(NSArray *)fileTypes; ❌
7、可以使用“and”
来链接两个单独的操作
- (BOOL)openFile:(NSString *)fullPath withApplication:(NSString *)appName andDeactivate:(BOOL)flag;
属性方法命名
1、名词属性格式
- (type)noun;
- (void)setNoun:(type)aNoun;
例如:
- (NSString *)title;
- (void)setTitle:(NSString *)aTitle;
2、形容词属性格式
- (BOOL)isAdjective;
- (void)setAdjective:(BOOL)flag;
例如:
- (BOOL)isEditable;
- (void)setEditable:(BOOL)flag;
3、动词属性格式(动词现代式)
- (BOOL)verbObject;
- (void)setVerbObject:(BOOL)flag;
例如:
- (BOOL)showsAlpha;
- (void)setShowsAlpha:(BOOL)flag;
4、不要使用分词将动词转换为形容词
- (void)setAcceptsGlyphInfo:(BOOL)flag; ✅
- (BOOL)acceptsGlyphInfo; ✅
- (void)setGlyphInfoAccepted:(BOOL)flag; ❌
- (BOOL)glyphInfoAccepted; ❌
5、可以使用情态动词(can
, should
, will
等)来提高清晰性,但不要使用do
或 does
- (void)setCanHide:(BOOL)flag; ✅
- (BOOL)canHide; ✅
- (void)setShouldCloseDocument:(BOOL)flag; ✅
- (BOOL)shouldCloseDocument; ✅
- (void)setDoesAcceptGlyphInfo:(BOOL)flag; ❌
- (BOOL)doesAcceptGlyphInfo; ❌
6、只有在方法需要间接返回多个值的情况下才使用 get
- (void)getLineDash:(float *)pattern count:(int *)count phase:(float *)phase;
Delegate方法命名
1、用于通知委托对象操作即将发生或已经发生的方法名中要使用 did
或 will
- (BOOL)browserDidScroll:(NSBrowser *)sender;
- (NSUndoManager *)windowWillReturnUndoManager:(NSWindow *)window;
2、用于询问委托对象可否执行某操作的方法名中可使用did
或 will
但最好使用 should
- (BOOL)windowShouldClose:(id)sender;
集合对象方法命名(Array、Set、Dictionary、Table等)
集合对象(集合中的对象被称之为元素)约定要具备如下形式的方法
- (void)addElement:(elementType)anObj;
- (void)removeElement:(elementType)anObj;
- (NSArray *)elements;
例如:
- (void)addLayoutManager:(NSLayoutManager *)obj;
- (void)removeLayoutManager:(NSLayoutManager *)obj;
- (NSArray *)layoutManagers;
- (void)insertLayoutManager:(NSLayoutManager *)obj atIndex:(int)index;
- (void)removeLayoutManagerAtIndex:(int)index;
方法参数命名
1、参数采用小驼峰命名
2、不要在参数名中使用 pointer
或 ptr
,让参数的类型来说明它是指针
3、避免使用 one
, two
,...,作为参数名
4、避免为节省几个字符而缩写
按照 Cocoa
惯例,以下关键字与参数联合使用
...action:(SEL)aSelector
...alignment:(int)mode
...atIndex:(int)index
...content:(NSRect)aRect
...doubleValue:(double)aDouble
...floatValue:(float)aFloat
...font:(NSFont *)fontObj
...frame:(NSRect)frameRect
...intValue:(int)anInt
...keyEquivalent:(NSString *)charCode
...length:(int)numBytes
...point:(NSPoint)aPoint
...stringValue:(NSString *)aString
...tag:(int)anInt
...target:(id)anObject
...title:(NSString *)aString
xcassets
1、按模块分目录,目录首字母大写,大驼峰命名
|--CreateOrder
|--DispatchOrder
|--OrderDetail
2、图片命名格式:模块名称__ 页面名称 __ 控件名称[__状态名称]
|--CreateOrder
| |--createOrder_selectAddress_okButton_normal
| |--createOrder_selectAddress_okButton_highlighted
| |--createOrder_selectAddress_okButton_disabled
| |--createOrder_selectAddress_okButton_selected
| |--createOrder_selectAddress_okButton_focused
strings
1、按模块分组
// 下单模块
...
...
// 派单模块
...
2、文案键值对,键全大写,格式:模块名称__ 页面名称 __ 控件名称[__状态名称]
// 下单模块
"CREATEORDER_SELECTADDRESS_OKBUTTON_NORMAL" = "完成";
"CREATEORDER_SELECTADDRESS_CANCELBUTTON_NORMAL" = "取消";
// 派单模块
"DISPATCHORDER_ORDERCARD_RECREATEBUTTON_NORMAL" = "重新下单";