极客班 Objective-C 高级编程(二)
课堂笔记
@段松 老师上课喜欢类比生活中的对象,还是比较容易理解的。
断点的使用可以帮助理解每一行的作用和追踪对象或属性的变化。
内存管理讲的挺详细,发现课程结构顺序和《iOS 编程》很像。
@段松 老师上课喜欢类比生活中的对象,还是比较容易理解的。
断点的使用可以帮助理解每一行的作用和追踪对象或属性的变化。
内存管理讲的挺详细,发现课程结构顺序和《iOS 编程》很像。
startup:账号系统,登陆系统,setting,有时间的组员可以多做一点
项目变化,很正常,确定人员分配,推动项目往前走。
我们小组的项目“一秒”:需求真实性,目的在哪里,目标用户为什么会用,解决什么问题。
添加一个主题:亲子成长,空气环境变化。
分享带有主题的视频,类似 iMovie 的手机版
很多时候需求都是你自己猜想的,产品的使用场景,都是需要验证的!
言语表达要求很高。
语言描述要准确,不一定要非常简练华丽。
@李建忠: A good thinker is a good talker.
例子:上班很远,并不是所有人都是问题,并不是所有人都一样的界定。所以提供的解决方案都不一样,用户真实的上班方式开车自行车走路,又该如何解决?要面对面访谈用户,电话次之。
产品探索过程中,要抛弃自己的创意和解决方法,重点在用户的需求和相应的解决方案,最后收敛(投票和排序重要性)成一个产品。
所有人:销售运营开发测试产品经理坐在一起产品的逻辑推理,然后才能进行用户访谈。
用户细分,不然找错人浪费了时间经理。
这一套做产品思维,可以用工作中,如正在培训的创业公司敏捷开发。
不要让天使用户看到你的访谈的问题。
热点事件来分析,提高逻辑推理。推荐《系统化思维导论》。
最近在看《精益数据分析》。
用户群不要混合现有用户群来定义你的用户群,如:色影无忌和蜂鸟网
用户发现问题->寻找解决方案->找到产品->愿意付费
我是 iOS 学员,关于产品方面听来挺过瘾。多谢 Tele Deng 的笔记:【极客班-精益产品探索】第一周课堂笔记。
说话真心快
创业中:健美乐
过去培训经验:5小时 * 12天完成培训,走向职场。
不是看了多少书,死记硬背了多少知识点,更多是写代码的能力,写的多了自然会用了。
学习过程中类比现实生活中的东西,可能比较容易理解。
代理就是委托,力有不逮时,联系朋友去完成。
学习方法:就是梳理大纲知识点,掌握要点,理清楚后,自己写代码自然就会了。
先学习整体框架,后学习细节。
UITabBarViewController 90%使用的框架。
UITableView
实战中的两种应用框架(后续课程)
查看开源项目,删除多余的部分,只看自己关注的部分。最基本也要会用开源框架。
iOS 数据结构用的不多。
分享易庆晟的笔记:GeekBand第二周线下课堂,总结的非常好。
分享 X-Lion 的 C++ 笔记:极客班GeekBand - C++第一次课程辅导 - 李建忠,和于航的笔记:GeekBank极客班C++线下班学习心得(二)。
均衡组员分配,iOS/C++/PM,考虑到产品上线审核产生的延迟,要提前两周就要完成项目,约9月12日。
基于 MVP,产品原型图和技术要点分解同步进行,快速迭代,让真实项目催促你前进。
一天下来,我们小组项目最终打磨为:“一秒变大人”,张诚 PM、我和易庆晟iOS 方面、郭意亮 C++ 技术、还有新加入的沈秋艳 PM,希望尽快下周末前出第一个版本。
我负责项目图片视频处理方面,TODO:
-阅读图片视频相关的文档
-objc.io 关于图片视频的小节
-找几个相关开源的项目
Swift or Objective-C?虽然两门课都有,但是我还是❤️Swift,并不仅仅因为❤️Taylor。
栈对应方法或函数的帧,堆则是包含大量 iOS 应用创建的对象
引用计数就是社保局,调查每个人有几份工作,一个正式工作,或兼职几份工作,或失业。失业,内存就会被释放,就会给你这个 free man 推荐新工作。
那些情况会使对象失去拥有者:
当对象没有拥有者时,指针变量的内存就该被释放。
大部分强引用循环可以确定一个父子关系,子对象改为弱引用即可。
Xcode 的 Leaks 工具可以帮忙找出强引用循环问题。
声明属性,等于隐式地声明和创建相应名称的实例变量,声明一对存取方法。当然我们还可以自定义存取方法。
属性的特性(attribute):
网站加了一个 hexo-filter-auto-spacing 插件,中英文之间自动加空格😊
类和对象。对象通过实例变量保存属性的值。
类有方法,类似函数,调用对象的方法一般叫发消息。
1 | [ partyInstance addAttendee: somePerson |
方法的唯一性取决方法名。
实例变量的存取方法:get 和 set
发消息的三种语法:
类方法和实例方法区别:
类方法的初始化
必须选一个指定初始化方法,其他初始化方法可以调用指定初始化方法,形成一个初始化方法链
数组对象只能保存指向 Objective-C 对象的指针,不能保存基本类型和 C 结构加入数组对象。当然包装成 Objective-C 对象,就可以了,如 NSNumber、NSValue 和 NSDate。nil 包装成 NSNull 才能加入数组。
Slide 中图太多就不一一贴在这里了
UINavigationController 比喻成一堆卡片,只能看到一张卡片。新的 MVC 出来,旧的就被丢弃。
Segue 总是引导到一个新建的 MVC,旧的同样被丢弃。
Storyboard 总是通过名字连接代码的:UIView 的 Class、View Controller 的 Class、Outlet 的名字、IBAction 的名字,这是一种松散耦合,能够这个两件东西连接起来。
最好的理解就是做实践(Demo)。
我们将会新建一个 Psychologist MVC
Psychologist 将会披露他的诊断,通过 segue Happiness MVC。
我们会把 MVCs 放进 navigation controllers 内部 split view controllers,它将兼容 iPad 和 iPhone 设备。
Autolayout 另一个技巧是使用 Reset to Suggested Constraints,配合 Size Inspector 面板里 Descendant Constraints。
Popover 对应的是 popoverPresentationController
由于 Popover 出来的 MVC 每次的新建的,History 相关信息可以存储到 NSUserDefaults 中。
iPad 是小的弹窗,iPhone 默认 Modal,可以改回 Popover。
可以UIPopoverPresentationControllerDelegate协议,重写 UIViewController 中的 preferredContentSize 自定义大小。
网站添加 Tags,方便分类查找文章。 Medium 非常简洁优雅,可以借鉴。网站改版和文章排版比较耗费时间,以后要以内容输出优先。
关于课程中 Swift 语言的知识我只是简单浏览一遍,毕竟他说的也不详细,真正搞懂还是要系统学习。复习一下《疯狂 Swift 讲义》或者 Google 都是可行的。重要是 Demo 实践。今天微博看到的玩笑:Computer Programming To Be Officially Renamed “Googling Stackoverflow” 。
Demo: 自定义 UIViews in your storyboard (FaceView)
如何在iOS 8中使用Swift和Xcode 6制作精美的UI组件 有个例子:苹果在Xcode 6中加入了两个新的Interface Builder(下文用IB简称)属性声明:IBInspectable和IBDesignable。IBInspectable在IB的Attribute Inspector(属性检查器)中查看类的属性,而IBDesignable能实时更新视图,很厉害吧!
是寄于 HappinessViewController 里的 happiness,不同于 smiliness。
扩展
协议也是一种数据类型
代理是一种非常重要的协议的应用。
代理是我们完成视图和控制器盲沟通的方式。
通过代理模式 UIViews 可以控制 Model,虽然并不是真的拥有 Model。
如何实现:
现在视图就勾住了控制器。不过视图仍不晓得控制器的内容,所以视图仍是通用/可重复使用的。
Demo: Happiness MVC’s Model using generic FaceView in its View
Cmd + Shift + O 快速打开文档,有种 Xcode 内置 spotlight 的即视感。
FaceView.swift 为自定义 UIView 的类,是 View。
HappinessViewController.swift 是继承自 UIViewController,是 Controller。
View 中 dataSource 是 protocol FaceViewDataSource 的属性(代理或数据源),作为 dataSource?.smilinessForFaceView(self) 的形参。
Controller 实现了该协议,并将自己作为代理的对象,并通过 happiness 变量来改变协议中
Controller 中的 faceView 通过 Outlet 监控 dataSource 值的改变(didSet),来控制 View 笑脸的变化(smiliness)。
1 |
|
1 | // HappinessViewController.swift |
手势识别分两步走:
Usually the first is done by a Controller
Though occasionally a UIView will do this itself if the gesture is integral to its existence
The second is provided either by the UIView or a Controller Depending on the situation. We’ll see an example of both in our demo.
Imagine we wanted a UIView in our Controller’s View to recognize a “pan” gesture …
上面的代码造成排版错误,估计代码高亮产生的,先换成图片。
This is just a normal outlet to the UIView we want to recognize the gesture
We use its property observer to get involved when the outlet gets hooked up by iOS
Here we are creating an instance of a concrete subclass of UIGestureRecognizer (for pans)
The target gets notified when the gesture is recognized (in this case, the Controller itself)
The action is the method invoked on recognition (the : means it has an argument)
Here we ask the UIView to actually start trying to recognize this gesture in its bounds
Let’s talk about how we implement the handler …
So each concrete subclass provides special methods for handling that type of gesture
For example, UIPanGestureRecognizer provides 3 methods
func translationInView(view: UIView) -> CGPoint
// cumulative since start of recognition
func velocityInView(view: UIView) -> CGPoint
// how fast the finger is moving (points/s)
func setTranslation(translation: CGPoint, inView: UIView)
This last one is interesting because it allows you to reset the translation so far
By resetting the translation to zero all the time, you end up getting “incremental” translation
The abstract superclass also provides state information
var state: UIGestureRecognizerState { get }
This sits around in .Possible
until recognition starts
For a discrete gesture (e.g. a Swipe), it changes to .Recognized
(Tap is not a normal discrete) For a continues gesture (e.g. a Pan), it moves from .Began
thru repeated .Changed
to .Ended
It can go to .Failed
or .Cancelled
too, so watch out for those!
So, given this information, what would the pan handler look like?
func pan(gesture: UIPanGestureRecognizer) {
switch gesture.state {
case .Changed: fallthrough
case .Ended:
let translation = gesture.translationInView(pannableView)
// update anything that depends on the pan gesture using translation.x and .y
 gesture.setTranslation(CGPointZero, inView: pannableView)
default: break
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
Remember that the action was “pan:” (if no colon, we would not get the gesture argument)
We are only going to do anything when the finger moves or lifts up off the device’s surface
fallthrough means “execute the code for the next case down”
Here we get the location of the pan in the pannableView’s coordinate system
Now we do whatever we want with that information
By resetting the translation, the next one we get will be how much it moved since this one
### 常用手势:
- UIPinchGestureRecognizer
var scale: CGFloat // not read-only (can reset)
var velocity: CGFloat { get } // scale factor per second
- UIRotationGestureRecognizer
var rotation: CGFloat // not read-only (can reset); in radians
var velocity: CGFloat { get } // radians per second
- UISwipeGestureRecognizer
Set up the direction and number of fingers you want, then look for .Recognized
var direction: UISwipeGestureRecoginzerDirection // which swipes you want
var numberOfTouchesRequired: Int // finger count
- UITapGestureRecognizer
Set up the number of taps and fingers you want, then look for .Ended
var numberOfTapsRequired: Int // single tap, double tap, etc.
var numberOfTouchesRequired: Int // finger count

### Demo: Happiness pinch and pan
**FaceView Gestures**
Add a gesture recognizer (pinch) to the FaceView to zoom in and out (control its own scale)
Add a gesture recognizer (pan) to the FaceView to control happiness (Model) in the Controller
```
// FaceView.swift 部分代码
import UIKit
protocol FaceViewDataSource: class {
func smilinessForFaceView(sender: FaceView) -> Double?
}
// 2. handler
func scale(gestrue: UIPinchGestureRecognizer) {
if gestrue.state == .Changed {
scale *= gestrue.scale
gestrue.scale = 1
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
// HappinessViewController.swift 部分代码
import UIKit
class HappinessViewController: UIViewController, FaceViewDataSource
{
@IBOutlet weak var faceView: FaceView! {
didSet {
faceView.dataSource = self
// 1. Adding a gesture recognizer
faceView.addGestureRecognizer(UIPinchGestureRecognizer(target: faceView, action: "scale:"))
// try in storyboard
// faceView.addGestureRecognizer(UIPanGestureRecognizer(target: self, action: "changeHapponess:"))
}
}
// 通过 storyboard 添加 Pan Gesture Recognizer,然后 storyboard 添加 IBAction 到 Controller 中
private struct Constants {
static let HappinessGestureScale: CGFloat = 4
}
@IBAction func changeHappiness(gesture: UIPanGestureRecognizer) {
switch gesture.state {
case .Ended: fallthrough
case .Changed:
let translatrion = gesture.translationInView(faceView)
let happinessChange = -Int(translatrion.y / Constants.HappinessGestureScale)
if happinessChange != 0 {
happiness -= happinessChange
gesture.setTranslation(CGPointZero, inView: faceView)
}
default: break
}
}
var happiness: Int = 3 { // 0 = very sad, 100 = ecstatic
didSet {
happiness = min(max(happiness, 0), 100)
print("happiness = \(happiness)")
updateUI()
}
}
func updateUI() {
faceView.setNeedsDisplay()
}
func smilinessForFaceView(sender: FaceView) -> Double? {
return Double(happiness - 50) / 50
}
}
>有待翻译
## 5. 拓展阅读
[UIGestureRecognizer Tutorial: Getting Started](http://www.raywenderlich.com/76020/using-uigesturerecognizer-with-swift-tutorial)
## 项目代码保存在我的 GitHub: [CS193P-2015](https://github.com/gewill/CS193P-2015)
还是@段松 老师,讲解了 Xcode 常用的设置。还有楼房设计和楼房建造对应软件设计框架和代码实现。
熟悉 Xcode
一个 iOS 应用的构成详解
iOS 应用的生命周期
一款 iOS 应用是如何产生的?
看了7遍需求文档,心中自然有了成了一个原型图,甚至找到需求中缺乏的组件。
曾经辍学做过建筑,就有了下面比喻,很形象好理解:
项目开发流程图:
@段松 老师有7年的iOS研发经验,一线大牛我喜欢,奇幻之旅就正式开始吧。
iOS 开发和盖房子差不多,那么我们就先学习一些基本建筑材料:数据类型与操作符。后面还有一些数组、运算符、流程控制语句、枚举、结构体和宏定义等。
虽然这些之前都有学过,也算温故知新吧。和 Swift 相比确实繁琐古老的一些。
1 | NSInteger age = 18; |
极客班线下翻转课堂第一周,坐标浦东软件园,时间7月19日。
一天下来学习不少关于开发和产品的干货,感觉获益匪浅,但是还是要以后的学习和项目中实践可能才会理解透彻。本来参加极客班,是因为一个人独自钻研太累进展缓慢,现在感觉豁然开朗,信心十足,最主要的是有了学习的精神头,希望这一份主动性能够持续下去。既然 iOS 是我兴趣爱好,完成线上课程的同时,完成自我管理自律,明天图书馆约起。
课程安排的是线上课堂和项目实践同时进行,我想也多少和 Tiny 老师提到的学习方法相通:先了解官方文档 Guidelines,Release note,Documentation,理清楚技术架构关系,项目实际使用技术重点学习突破,也就完成了项目(大意如此)。
今天最大缺憾是没有和老师同学很好的交流,无论是上台提创意,提问题,听课有疑问没有去请教。一则我一直性格害羞内向,二则因为一造成的缺乏想法表达能力和技巧。性格弱我早就知道,天天提醒自己最棒能做好,希望能一点点进步。
以下是课程安排:
一部分同学是网络,开发,室内设计,摄影,大三,多是因为兴趣爱好报名的。但更多的都已经是几年的开发经验,还有几个是5-10年的,没有开发工作经验的我要努力了,不能落了后。
线下班推你下水,逼你学会游泳。真实做项目中学习技术。
推荐 iOS 样板项目供同学选择:
全栈:建筑学-掌握全局
实际项目需要技术和知识,如何组合运用到项目中,再去详细学习。培训目的,自主学习,遇到具体的难题可以提问。
创业: Zero to One,先失败,项目火之前少有人认同,先做一个简版让客户评判
项目管理:项目迭代去做,MVP,如:10行代码,成就感,
PM 和程序员关系,需求优先级往往没说,程序员分功能评估时间。两者之间的如何协作好,进度表中的关键:细分技术评估时间,确定优先级。
融资->招人->离职,半年才招齐人
创业泥潭,产品不温不火,添加不靠谱功能
UX 优先级低于功能实现
先站出来才有人认识你,占尽便宜
以后课堂不说了,只接受提问交流
经历:Unix/SA->SP->Python->OC
写代码自我要求,优秀。不要用直接抄袭其他产品。
知识像产品迭代,每次看一个知识都会不一样的理解。能讲解一个知识或技术,说明真的懂了。例如:UIObject等的继承关系。
算法原理与实践 课程知识梳理。
互联网:UGC(User-generated content)、用户互动、公司基因创始人背景专业
组团学习重要性,学习是动词
证书不重要,重要的是真正学习成长
重分享:output 带动 input
TODO:第一周的功能列表,团队 GitHub账号
我选了信贷员工具项目。
Bridging
Swift 可以无缝使用以前 Objective-C 的 API,但是一些特殊的数据类型需要桥接。桥接是指可以互换的使用。
NSString <-> String
NSArray <-> Array
NSDictionary <-> Dictionary<NSObject, AnyObject>
Int, Float, Double, Bool -> NSNumber (反之不行)
99%的桥接均是隐式完成的。
属性列表指 AnyObject 是一下六种类型的集合列表:
NSString, NSArray, NSDictionary, NSNumber, NSData, NSDate。
处理属性列表通常需要映射:如 is 和 as。
属性列表可以“盲”传递数据,也可以作为一种通用数据结构-类似泛型。
NSUserDefaults 作为一种使用属性列表的存储机制。本质上就是一个小的存储数据列表的数据库。通常用存储“设置”信息。
NSUserDefaults 可以通过名称或键来存储或检索整个属性列表。
以下用法摘自:NSUserDefaults — A Swift Introduction
1 | let defaults = NSUserDefaults.standardUserDefaults() |
NSUserDefaults 常用的写入方法:
iOS 8或更新版本不要使用 synchronize。
1 | let defaults = NSUserDefaults.standardUserDefaults() |
对应的常用读取 NSUserDefaults 的方法:
方便在一处修改,容易理解编译报错。
1 | let userNameKeyConstant = "userNameKey" |
视图代表了一个长方形区域。
视图是等级,类似单继承:一个视图只可以有一个 superview,但可以有很多 subviews。
1 | // |