斯坦福大学swift课程笔记

接到任务需要将Chromecast的iOS sender给实现一下,但是iOS基础太薄弱了,进行了一段时间感觉困难重重,需要系统得学习一下基础知识。所以在youtube上看了一下斯坦福大学的iOS教学视频,那位老师讲得非常棒,为了避免遗忘,记一下听课的笔记。

Lecture 5

View的更新

  • 在View上面添加@IBDesignable可以在storyboard中看到效果。
  • 在变量上面添加 @IBInspectabl可以在storyboard中改变这些变量值,查看改变后的变化效果。运行的时候回应用改变的值。
  • 当改变一个变量的值需要UI重绘的时候可以使用didSet:

    1
    2
    3
    4
    5
    var 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
    11
    func 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
    17
    UIPinchGestureRecognizer
    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
    12
    func 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
4
brain.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
2
3
4
let url = NSURL(string: stringUrl)
if let imageData = NSData(contentsOfURL: url){
image = UIImage(data: imageData)
}

Lecture 8

扩展UINavigationController

1
2
3
4
5
6
extension UIViewController {
var contentViewConttroller: UIViewController {
if let navcon = self as? UINavigationController {
return navcon.visibleViewController ?? self
} else {
return self

多线程

同Android一样,有一个更新UI的主线程,其它耗时任务放在其它线程里进行。

开一个新线程

1
2
3
4
let queue: dispatch_queue_t = dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)
dispatch_async(quese){
//do something
}

使用主线程

1
2
3
4
5
6
7
let mainQ: dispatch_queue_t = dispatch_get_main_queue()
dispatch_async(not the main queue) {
//do a non-UI jos
dispatch_async(dispatch_get_main_queue){
//call UI functions
}
}

代码创建segue

1
performSegueWithIdentifier(Storyboard.ShowInamge, sender:sender)

Lecture 9

UITableVIew

同Android里的listview

调整每个item的高度自适应

1
2
tableView.estimatedRowHeight = tableVie.rowHeight
tableView.rowHeight = UITableViewAUtomaticDimension

Lecture 12

Auto layout

  • 只有iPad的原始尺寸的大小,其他的都有压缩

    Lecture 13

NSTimer

  • 只能在主线程中使用
    1
    2
    3
    4
    5
    6
    7
    8
    9
    let 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
2
3
4
5
6
7
8
9
10
let center =NSNotificationCenter.defaultCenter()
var observer = center. addObserverForName(UIContentSizeCategoryDidChangeNotification,
Object: UIApplication.sharedApplication(),
queue: NSOperationQueue.mainQueue())
{
notification in
// do somethinf
let c = notification.userInfo?[UIContentSizeCategoryNewValueKey
}
center.removeObserver(observer)

发送

1
2
3
4
5
6
let notification = NSNotification(
name:String,
object: AnyObject?,
userInfo:Dictinary
)
NSNotificationCenter.defaultCenter().postNofification(notification)

Alert

  • 在屏幕中间弹出
  • 一般就一两个选项如ok,cancel
  • 打断用户交互,慎重使用
  • 经常用来处理同步的问题,如网络中断等
  • 可以有个text field来接收用户输入

Action Sheets

  • 从底部滑入
  • 可以从 bar button item 或者其它矩形区域展现
  • 一般询问杜宇两个回答的问题
  • 可以理解为给用户一堆选择
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
var alert = UIAlertController(
title: "redeploy Cassini",
message: "message",
preferredStyle: UIAlertControllerStyle.ActionSheet// .Alert
))
alert.addAction(UIAlertAction(
title: "title",
//style: .Destruction)// 红色显示
//style: .Cancel
style, UIAlertActionStyle.Default){
(action:UIAlertAction) -> Void in
//go to somewhere
}

presentViewController(alert, animated: true, completioon: nil)

Lecture 17

Dismiss a view controller

1
func dismissViewControllerAnimated(Bool, completion: () -> Voie)

Embed Segues

将一个mvc的view放到另外一个mvc的View里面