If a segue can be triggered only programmatically, you usually draw the connection arrow directly from the source view controller to the destination view controller.
NSObject 分配对象的类方法有 [+ alloc] 和 [+ allocWithZone:],alloc内部其实调用的就是 [+ allocWithZone:]。并且在 Objective-c2.0 中 [+ allocWithZone:] 的参数zone会被忽略。[+ new] 方法是 [+ alloc] 方法和 [- init] 方法的结合,如果使用[[NSObject alloc] init]
会让代码风格更统一,直接使用[NSObject new]
则使代码更简洁。
要区分设备方向和界面方向,设备方向是指物理设备的方向,可以通过[UIDevice currentDevice].orientation
获得。而界面方向则是指应用的界面支持哪些方向,当设备旋转到某一方向时,若应用界面支持这一方向,则应用界面也会随之旋转变化。应用支持的界面方向可以在项目的 target 中设置。另外我们可以在 Application Delegate 对象中实现方法 [- application:supportedInterfaceOrientationsForWindow:] 来覆盖
target 中的设置。最后是View Controller级别的设置,UIViewController 类中包含两个方法 [- shouldAutorotate] 和
[- supportedInterfaceOrientations]。只有当 [- shouldAutorotate] 方法返回 YES 时,[- supportedInterfaceOrientations] 方法才会被调用。如果是iPad,supportedInterfaceOrientations方法默认返回所有方向,如果是 iPhone,该方法则默认返回除竖向反向外的其他方向。一个界面最终支持的方向是两种级别支持方向的交集。
通过 xib 文件指定 view controller 的 view 时,初始化 view controller 使用的方法是
[- initWithNibName:bundle:]。当xib文件的名字与 view controller 的名字相同时,直接使用 [- init] 方法初始化 view controller 也可指定其
view 为 xib 文件中的 view。经测试发现在调用 UIViewController 的
init 方法之前,self 的 nibName 属性在有同名 xib 的情况下已赋值为该名称,之后 [- init] 方法会调用 [- initWithNibName:bundle:] 方法,但传入的参数为 null,而 [- initWithNibName:bundle:] 方法在参数为
null 的情况下会去搜寻 nibName 属性指定的xib文件加载,所以在有同名xib文件时, [- init] 的方法也可加载到 xib 文件,但暂时没有看到官方说明,所以即使是同名的xib文件,也最好用 [- initWithNibName:bundle:] 方法去加载 xib 文件初始化 view controller。
通过 Interface Builder 搭建的界面 xib 文件本质上是 XML 文档,它保存了界面上所有对象的信息和其之间的联系。编译时,xib 文件会被编译成二进制的 nib 文件(读取xml文件,生成所有界面对象,调用 encodeWithCoder 序列化为二进制 nib 文件)。运行时,反序列化,调用所有对象的 initWithCoder,最后生成所有界面元素的实例,向实例发送 awakeFromNib 消息。所以,所有控件都支持initWithCoder 和 encodeWithCoder 的 NSCoding 规范。如果直接通过 xml 文件解析生成实例对象应该会影响性能。
通过 UITableView 和 UICollectionView 显示数据时,当数据变为空时,一般要显示没有数据的提示信息,随着数据的改变,一般会伴随着 reloadData 方法的调用或者 cell 的插入或删除的方法的调用,而此时都会触发 delegate 的 numberOfRowsInSection 方法,将提示信息的显示和隐藏的判断放在这里不容易遗漏一些改变的情况。
iOS 通过设备可以获取三类事件:Multitouch events,Accelerometer events,Remote control events。一个多点触控序列表示从第一根手指的触摸屏幕开始到最后一根手指的离开的过程。在这个过程中,一个 UITouch 的对象代表一根手指在屏幕上的触摸或者移动,并更新它的 phase,location in a view,previous location等属性,当有新的
UITouch 对象或已有 UITouch 对象更新,UIApplication 对象会将
UITouch 对象传给 key window 对象,之后 window 对象通过
hitTest:withEvent:(内部调用pointInside:withEvent:)确定 touch 真正触发的 view,如果有 gesture recognizer 附加在该view上,
window 对象会先将touch对象先传给gesture recognizer,然后
window 会根据 gesture recognizer 的识别结果来决定是否发送消息给真正的触发的view或者发送取消事件的消息,当事件消息发送给view时,即可根据 responder chain 来处理事件,通过 nextResponder 来传递。
偶然跑一个老的项目时发现,由于该项目没有对iPhone的4.7寸和5.5寸屏幕适配,所以当应用运行在新尺寸的设备上时,系统会将应用的界面整体放大到占满整个屏幕(例如高度固定20点的status bar已明显超过该值)。若不想应用按此方法展示,则可以:
- 在应用的Target->General中设置Launch Screen File。当将一个.storyboard或.xib文件设置为Launch Screen File时,应用在所有尺寸的iPhone上都会全屏显示,并且不会整体的缩放。设置Launch Scrren File的作用就是可以通过一个文件,对不同尺寸的设备以及在不同方向上适配不同的启动界面。
- 若通过在.xcassets中设置静态图片LaunchImage的方式,则可以加入对新尺寸图片。之后应用的效果也会变为全屏显示,不会整体放大了。
发现启动图片的设置对应用展示方式的影响后,做了一个不同情况的统计测试:
- 若不设置任何的启动资源(静态图片或文件),或者只设置了3.5寸屏的启动静态图片,此时的感觉像系统认为所有界面针对3.5寸屏设备做展示,在3.5寸上会全屏展示,各种bar的高度也肯定是默认值。若在4寸设备上运行,因为3.5寸屏与4寸屏宽相同,则在4寸设备上会按3.5寸屏的尺寸居中显示,上下会有黑边。4.7寸屏和5.5寸的宽高比与4寸相同,但宽度都大于4寸和3.5寸的320点宽,所以在这两个设备上会按宽度等比放大然后居中显示,同样上下都会留有黑边。
- 若设置了4寸屏的启动图片,则3.5寸和4寸屏都会全屏适配显示,但4.7寸和5.5寸会按4寸等比放大显示。
- 若设置了4.7寸或5.5寸屏的启动图片或者使用启动屏幕文件的形式,则所有屏幕都会全屏适配显示。
暂时没有找到官方的关于这方面的说明。
UIView 内设置边框宽度(layer.borderWidth)向 view 内延伸,不会占用 view 外部空间。
在 Objective-C 中,协议可以继承,当类声明实现子协议时,编译器也会提示父协议中的方法。
测试 Demo 一般会创建新的工程,如果想测试应用运行在旧版本系统模拟器上的效果,可能会在 Destination 的模拟器列表里看不到已添加的旧版本模拟器,这时要注意应用的 Deployment Target 是否设置为支持所要测试的旧版本系统及以下。
通过 UIController 的 automaticallyAdjustsScrollViewInsets 属性,可以设置系统是否调整 scroll view 以防止被 navigation bar 等遮挡。但是该属性在 iOS11 中被废弃,代替的是 UIScrollView 的 contentInsetAdjustmentBehavior 属性。
当界面上只有一个 scroll view 时,点击状态栏可以将其内容滚动回顶部。但如果同时存在多个 scroll view 则该功能不起作用,原因是这一行为受 scroll view 的属性 scrollsToTop 的影响,iOS 系统只允许同时有一个 scroll view 的该属性为 YES,这时这一个 scroll view 可以使用该功能,当有多个 scroll view 的该属性为 YES 时,则都不起作用。解决办法就是根据需求动态的修改 scroll view 的 scrollsToTop 属性。