接到任务需要将Chromecast的iOS sender给实现一下,但是iOS基础太薄弱了,进行了一段时间感觉困难重重,需要系统得学习一下基础知识。所以在youtube上看了一下斯坦福大学的iOS教学视频,那位老师讲得非常棒,为了避免遗忘,记一下听课的笔记。
Lecture 5
View的更新
- 在View上面添加@IBDesignable可以在storyboard中看到效果。
- 在变量上面添加 @IBInspectabl可以在storyboard中改变这些变量值,查看改变后的变化效果。运行的时候回应用改变的值。
当改变一个变量的值需要UI重绘的时候可以使用didSet:
1
2
3
4
5var scale: CGFLoat = 0.90 {
didSet{
setNeedsDisPlay()
}
}按住Ctrl拖动view到ViewControler来创建一个View的实例对象
- 对于可选变量,使用的时候可以在后面加上默认值
1
var value = optionalVaule ?? 0
手势
- 手势由UIGestureRecognizer的子类来识别。
添加一个gesture recognizer到UIVIew并且提供一个handle方法来处理手势。
1
2
3
4
5
6
7
8
9@IBOutLet weak var pannableView: UIView{
dieset{
let recognizer = UIPanGestureRecongnizer(
//self 代表手势的接收者,(_:)表示方法有个参数
target: self, action: #selector(ViewController.pan(_:))
)
pannableView.addGestureReconginzer(recognizer)
}
}UIGestureRecognizer包含了一个状态信息:
1
var state: UIGestureRecognizerState {get}
- 其初始值为.Possible
- 当有离散手势(如点击)时,变为.Recognized
- 当有连续手势时,先是变成.Began, 然后是重复的.Changed, 最后是.Ended。
- 可能有.Failed或者.Cancelled
处理pan手势的handler方法:
1
2
3
4
5
6
7
8
9
10
11func pan(gesture: UIPangestureRecognizer) {
switch getsture.state {
case .Changed: fallthrough
case .Ended:
let translation = getsture.translationInView(pannableView)
//do some update
gesture.setTranslation(CGPoint
Zero, inView: pannableView)
default: break
}
}识别手势的类有:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17UIPinchGestureRecognizer
var scale: CGFloat
var velocity: CGFloat {get}
UIRotationGestureRecognizer
var rotation: CGFloat
var velocity: CGFloat {get}
UISwipeGestureRecognizer
// set up the direction and number of fingers you want, then look for .Recongnized
var direction: UISwipeGestureRecognizerDirection
var numberOfTouchesRequired: Int
UITapGestureRecognizer
// set up number of taps and fingers you want, then look for .Ended
var numberOfTapsRequired: Int
var numberOfTouchesRequired: Int
组合MVC
- UISplitViewController: 讲两个MVC并列放在一起
- UINavigationController: 就是一个MVC的栈
Lecture 6
Segues
- 一个MVC启动另外一个MVC叫做Segue,Segue总会创建新的MVC实例。
- 每个Segue都有个id, 在代码中用来识别不同的Segue.
Segue中包含源storyboad的id和目标MVC的controller
1
2
3
4
5
6
7
8
9
10
11
12func preparedForSegue(segue: UIStoryboardSegue, sender: AnyObject?){
if let identifier = segue.identifier {
switch identifier {
case "show graph":
if let vc = segue.destinationViewController as? GraphController {
vc .property1 = ..
vc.callMethodToSetItUp(...)
}
default: break
}
}
}在代码里发送segue
1
performSegueWithIdentifier(segue, sender: view)
使用字典来代替switch
- SplitViewController只能正常工作在iPad或者iPhone6S这种大屏设备上。要在手机上正常工作,需要选择Editor->Embed In->Navigation Controller
View Controller Lifecycle
- viewDidLoad: View 实例化后调用,可以做一些初始化操作,如根据Model来更新UI,比init方法更好,因为调用的时候outlets都会被准备好了。但是view的大小还没确定。类似于Android里面的onCreate.
- viewWillAppear: view将要在屏幕上显示的时候调用,所以会被多次调用,类似于Android里面的onStart.
- viewDidAppear: View 已经可见了,可以开始动画。类似于Android里面的onResume
- viewWillDisappear: view 将不可见,保存状态。类似于Android中的onPause.
- viewDidDisappear: view已经不可见了,类似Android中的onStop
- viewWillLayoutSubviews
- viewDidLayoutSubviews: 当一个view的frame发生改变,或者它的子view重新布局的时候被调用
- viewWillTransitionToSize: 横竖屏改变的时候调用
Lecture 7
Memory Management
引用类型都是存储在堆里,系统会自动对实例对象进行计数,当计数为0的时候就会回收。引用的类型包括: - strong: 指向的对象会一直保留在堆中。
- weak: 如果没有别的引用指向这个对象,那就设置为nil. 只能是可选类型
- unowned: 不要对其进行引用计数,有错误的时候直接crash
closure
会因为循环调用使内存无法释放,解决方式:1
2
3
4brain.addOperation("Z") { [ weak weakSelf = self ] in
weakSelf?.display.textColor = UIColor.redColor()
return sqrt($0)
}
当对象要从堆里被清 除的时候,deinit方法会被调用
Extensions
Extensions 可以让我们添加新方法、属性到一个class/struct/enum,无论有没有源码。
Protocols
一系列方法和属性的声明,类似于java中的接口
Delegation
View和Controller之间进行通信的方法,使用protocols实现。
图片加载
1 | let url = NSURL(string: stringUrl) |
Lecture 8
扩展UINavigationController
1 | extension UIViewController { |
多线程
同Android一样,有一个更新UI的主线程,其它耗时任务放在其它线程里进行。
开一个新线程
1 | let queue: dispatch_queue_t = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0) |
使用主线程
1 | let mainQ: dispatch_queue_t = dispatch_get_main_queue() |
代码创建segue
1 | performSegueWithIdentifier(Storyboard.ShowInamge, sender:sender) |
Lecture 9
UITableVIew
同Android里的listview
调整每个item的高度自适应
1 | tableView.estimatedRowHeight = tableVie.rowHeight |
Lecture 12
Auto layout
NSTimer
- 只能在主线程中使用
1
2
3
4
5
6
7
8
9let timer-NStimer.scheduledTimeWithTimeInterval(2.0,
target: self,
selector: #selector(fire(_:)),
userInfo: nil,
repeats: true
func fire(time: NSTimer) {
// do something
}
Animation
Animation 种类
Animating UIView properties - 变更边界和透明度
Animation of View Controller transitions
- Core Animation
- OpenGL -3D
- SpriteKit - 2.5D
- Dynamic Animation
Lecture 15
NSNotification
同Androd里的broadcast
注册
1 | let center =NSNotificationCenter.defaultCenter() |
发送
1 | let notification = NSNotification( |
Alert
- 在屏幕中间弹出
- 一般就一两个选项如ok,cancel
- 打断用户交互,慎重使用
- 经常用来处理同步的问题,如网络中断等
- 可以有个text field来接收用户输入
Action Sheets
- 从底部滑入
- 可以从 bar button item 或者其它矩形区域展现
- 一般询问杜宇两个回答的问题
- 可以理解为给用户一堆选择
1 | var alert = UIAlertController( |
Lecture 17
Dismiss a view controller
1 | func dismissViewControllerAnimated(Bool, completion: () -> Voie) |
Embed Segues
将一个mvc的view放到另外一个mvc的View里面