前言
这次的学习笔记不是从斯坦福大学的 Developing iOS 9 Apps with Swift 上来的,那个教程一周更新一次。这两天呢,我找了一些有意思的资料自己学习了。主要内容就是关于界面设计和 Swift 中的 init 方法。看了一些别的学习资料才发现,原来stanford的那个教程短短1小时20分钟,集合了好多好多东西,教授用自己的话精炼地总结出了很多容易犯错误的地方,以及我们应该重视的理论知识,那些理论知识我当时知道很重要,但就算听了好多遍,还是迷迷糊糊,因为我没有 learn by doing。在下文中,我会借用实例,进一步分析 Swift 中的初始化方法。
iOS APIs
iOS提供了大量的API使得它如此牛逼,整体架构可分为4层,分别是:
- Cocoa Touch
- Media
- Core Services
- Core OS
Core OS 是最接近物理层的,而 Cocoa Touch 是最接近用户的一层,也是我们使用最多的一层,起码对于我这小菜鸡来说,目前就只能先熟悉这一层啦。
那每一层里分别都包涵了什么呢?一下是 Stanford 课程里的几张图片。
在 Cocoa Touch 里,最重要的就是 UIKit 这个类库,这个类库包涵了control 组件,screen,事件响应等等,掌握了 UIKit,就有了与用户交互的资本了。
界面设计
就算掌握了那些API,可以使用并制作用户交互界面,也不能就此说成功了。我始终坚信一点,技术的意义在于让人更好的生活。用我另一篇文章《我心目中的“码农”》中的一段话来说就是:
「Engineers are versatile minds who create links between science, technology, and society」。
Engineer 的本质工作是设计,开发出应用于大众的产品。而代码只是一种工具。我并不认为这是什么产品经理之类的人干的事,我感觉这是作为app开发人员都应该具备的基本素质。最近学习了一些界面设计方面的知识,用 BITTIGER 的话总结就是:
- 左上右下:重要的信息(导航)在左上
- 面积匹配:功能使用率匹配功能面积
- 七条原则:列表不要超七条
- 广告独立:嵌入意识流广告
专门对几个app分析了一下,“超级课程表”,”斗鱼“,”ebay“,”简书“,还有很多其他的,基本上都符合”左上右下“,”面积匹配“,”七条“这几点,广告暂时离我有点远,就没有去琢磨。
功能性的重要内容,比如索引,导航,强调性的,播放器都放在左上角,起码都是从左上角开始延伸的。我的理解就是,需要人操作的,需要点击的重要的东西都是从左上角开始做的,那是人手指头操作最舒适的位置。
主要内容放中间,但是中间部分也是有先后顺序的,一般人都是从左往右看,所以客户最想要看的东西放左边,次要的放右边,比如新闻,比如私人定制的东西,私人歌单之类的,而不应该是叫客户付钱的按钮,付钱对老板重要,但客户心理上并不是那么”渴望“。还有一个有意思的地方就是,一个按钮宽度是一个屏幕的宽度,但高度不高,也就是一个小按钮,这样一列按钮,一般里面的内容都是居左的,而不是居中的,其实居中也符合情理,也是清晰可见,但大部分app都是居左。
列表长度不超过7条,我看到的一般都是显示4-5条,下方的导航栏一般为4个或者5个,从没见过6个。但我看了一眼我之前设计的app界面,6个。赶紧涂掉。突然觉得我有空得再好好看看 Norman 的 那本经典 - The Design of Everyday Things。
关于简约还是复杂
这一点,我觉得在做app之前很有必要思考一下。任何app都可以做的很复杂,功能齐全,就像 web 开发,有技术就行了,一个网页里乱七八糟的什么功能都可以放进去。但是我个人很讨厌那样的网站。
“ONE” 这个app其实做的挺一般(就技术而言),我所见的就有很多bug,但是它很火,首先内容很简单,应该说是简约,在如今繁华嘈杂的社会,它给了我们另一种别样的感觉,是清静,是停留,是给每个奔跑中的人一个歇脚的机会,反思,静听,或者只是单纯的发呆。这些不是代码所能满足的,不是一个简单的码农所能实现的。一个成功的app我想,并不是只有技术。
Swift init 方法
我在我的第一篇学习笔记 - Swift Learning Notes-1中记录过一些关于 designated init 和 convenience init 的 rules,我当时自以为理解了,但当我重新看了一遍喵神的 DESIGNATED,CONVENIENCE 和 REQUIRED 和 pupboss 的 Swift init方法的一些修饰符之后,我又感觉似懂非懂了。我现在再重新整理一下思路。
- Swift 的初始化有如此多的约束,非常严格的 rules,它的目的只有一个,就是安全。“Swift 中不加修饰的 init 方法都需要在方法中保证所有非 Optional 的实例变量被赋值初始化”[1]
- 在 init 中你可以设置任何属性的值,包括默认的值,甚至可以设置常量,也就是 let 申明的值。这并不违反 let 在 swift 中的含义,因为 init 只进行一次,初始化了之后就不会再变了。
- 有两种初始化类型,convenience 和 designated,
convenience
是一个关键字,也就是可以写成convenience init()
- init 里的顺序大致是,先完成你在本类中申明的,然后再调用父类的 init, 然后初始化父类继承过来的。
- convenience 只能调用本类中的 init,而且是必须在设置任何初始化属性之前,调用那个 init 方法。
- 如果你不实现任何的 designated 初始化,那么就会继承所有父类中的 designated。
- 如果 override 了所有父类的 designated 初始化,就会继承所有它的 convenience 初始化。这句话用 @onevcat 的话来说比较好一些 - “只要在子类中实现重写了父类 convenience 方法所需要的 init 方法的话,我们在子类中就也可以使用父类的 convenience 初始化方法了”。[1] 代码如下:
- 如果不实现任何的 init,就会继承所有的父类中的 inits。[2] 这句话可以解释 pupboss 中的那个例子,他说 “这里有一个有意思的现象,如果 SomeSubclass 里面有 override 或者什么都不写,才可以使用父类中的 convenience init 方法”。[3]
class superclass {
let numA: Int
init(num: Int) {
numA = num
}
convenience init(bigNum: Bool) {
self.init(num: bigNum ? 10000 : 1)
}
}
class subClass: superclass {
let numB: Int
override init(num: Int) {
numB = num + 1
super.init(num: num)
}
}
let anObj = ClassB(bigNum: false)
anObj.numA // 1
anObj.numB // 2
最后教授有一句话我比较感兴趣,“Try to stay away from inits, it's my advice to you.”[2] 开头他也讲过 init 用的不多,用的时候心中记着这些 rules 就好了。
by: 诸葛俊伟
喜欢我的请关注我哦~
-
DESIGNATED,CONVENIENCE 和 REQUIRED, 王巍(@ONEVCAT),http://swifter.tips/init-keywords/ ↩ ↩
-
Developing iOS 9 Apps with Swift, Stanford, https://itunesu.itunes.apple.com/WebObjects/LZDirectory.woa/ra/directory/courses/1104579961/feed ↩ ↩
-
Swift init方法的一些修饰符, pupboss, https://www.pupboss.com/swift-init-modifiers/ ↩