Stanford CS193p iOS開發(fā)課程筆記(十)

2015年12月16日

Stanford CS193p第十一課 Unwind Segues, Alerts, Timers, View Animation. 第十二課 Dynamic Animation


Unwind

  • Unwind Segue不會(huì)像其他Segue一樣創(chuàng)建一個(gè)新的MVC

Alerts/Action Sheets

  • 如何添加Alerts/Action Sheets
    1.創(chuàng)建button
    2.調(diào)用UIAlertController
    3.addAction
    4.調(diào)用presentViewController顯示Alerts/Action Sheets

這次在之前CassiniDEMO中加入了Alerts和Action Sheets.
點(diǎn)進(jìn)Cassini后點(diǎn)擊"Redeploy"彈出Action Sheets.
在Action Sheets中"Orbit Saturn"欄中實(shí)現(xiàn)了點(diǎn)擊跳出Alerts的功能

Action Sheets.png

Alerts.png
StoryBoard.png

具體代碼如下:

    @IBOutlet weak var redeploy: UIBarButtonItem!
    @IBAction func redeploy(sender: UIBarButtonItem) {
        //創(chuàng)建actionSheet
        let actionSheet = UIAlertController(title: "Redeploy", message: "Issue commands to Cassini'sguidance system.", preferredStyle: UIAlertControllerStyle.ActionSheet)
        //添加Action
        actionSheet.addAction(UIAlertAction(title: "Orbit Saturn", style: UIAlertActionStyle.Default, handler: { (action: UIAlertAction) -> Void in
            //此處實(shí)現(xiàn)了,點(diǎn)擊Orbit Saturn后跳出Alert
            let alert1 = UIAlertController(title: "Login Required", message: "Please enter your Cassini guidance system...", preferredStyle: UIAlertControllerStyle.Alert)//創(chuàng)建Alert
            //添加Action
            alert1.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
            alert1.addAction(UIAlertAction(title: "Login", style: UIAlertActionStyle.Default, handler: nil))
            //給Alert添加一個(gè)TextField
            alert1.addTextFieldWithConfigurationHandler { (textField) in
                textField.placeholder = "Guidance System Password"
            }
            
            //顯示TextField
            self.presentViewController(alert1, animated: true, completion: nil)
            
        }))
        
        
        actionSheet.addAction(UIAlertAction(title: "Explore Titan", style: UIAlertActionStyle.Default, handler: nil))
        
        actionSheet.addAction(UIAlertAction(title: "Closeup of Sun", style: UIAlertActionStyle.Destructive, handler: nil))
        
        actionSheet.addAction(UIAlertAction(title: "Cancel", style: UIAlertActionStyle.Cancel, handler: nil))
        
        //以下三行代碼用于iPad已POPover的形式顯示ActionSheets.在iPhone上不需要
        actionSheet.modalPresentationStyle = .Popover
        let ppc = actionSheet.popoverPresentationController
        ppc?.barButtonItem = redeploy
        
        //顯示actionSheet
        presentViewController(actionSheet, animated: true, completion: nil)
    }

Animation

  • iOS中動(dòng)畫的分類
    1.UIView Animation(視圖屬性的動(dòng)畫)
    2.Animation of View Controller transitions(viewController轉(zhuǎn)場(chǎng)動(dòng)畫)
    3.Core Animation
    4.Dynamic Animation(基于物理引擎的動(dòng)畫)

  • UIView Animation

  • 在其中我們主要能夠使用三種屬性,分別為:frame(意味著可移動(dòng));transform(意味著可旋轉(zhuǎn));alpha(意味著可改變透明度)

  • 使用:class func animateWithDuration(durationL NSTimeInterval, delay: NSTimerInterval, options: UIViewAnimationOptions, animations: () -> Void, completion: ((finished: Bool) -> Void)?)

    Example.png

  • UIViewAnimationOptions


    UIViewAnimationOptions.png
  • Dynamic Animation

  • 如何使用Dynamic Animation
    1.創(chuàng)建UIDynamicAnimator實(shí)例 var animator = UIDynamicAnimator(referenceView: UIView)
    2.添加UIDynamicBehaviors,如gravity,collisions等 let gravity = UIGravityBehavior() animation.addBehavior(gravity)
    3.添加UIDynamicItem let item1: UIDynamicItem = ...// usually a UIView gravity.addItem(item1)

  • UIDynamicItem protocol

protocol UIDynamicItem {
     var bounds: CGRect { get } 
     var center: CGRect { get set }
     var transform: CGAffineTransform { get set } //用于旋轉(zhuǎn)
}
  • Behaviors
    1.UIGravityBehavior有兩個(gè)重要屬性var angle: CGFloat //重力的角度 var magnitude: CGFloat //重力加速度
    2.UIAttachmentBehavior

    UIAttachmentBehavior.png

    3.UICollisionBehavior碰撞效果
    UICollisionBehavior.png

    4.UISnapBehavior震蕩效果
    5.UIPushBehavior把物體推向特定角度,速度恒定,可食一次性的效果,也可是持續(xù)效果
    6.UIDynamicItemBehavior控制對(duì)象之間如何交互
    UIDynamicItemBehavior.png

  • DropitDEMO

import UIKit

class dropitViewController: UIViewController,UIDynamicAnimatorDelegate {

    @IBOutlet weak var gameView: BezierPathsView!
    
    //創(chuàng)建DynamicAnimator
    lazy var animator: UIDynamicAnimator = {
        let lazilyCreatedDynamicAnimator = UIDynamicAnimator(referenceView: self.gameView)
        lazilyCreatedDynamicAnimator.delegate = self
        return lazilyCreatedDynamicAnimator
    }()
    
    //創(chuàng)建集成了三個(gè)Behavior的DropBehavior的實(shí)例
    var dropitBehavior = DropBehavior()
    
    var attachment: UIAttachmentBehavior? {
        willSet {
            animator.removeBehavior(attachment!)
            gameView.setPath(nil, named: PathNames.Attachment)
        }
        didSet {
            if attachment != nil {
                animator.addBehavior(attachment!)
                attachment?.action = { [unowned self] in
                    if let attacheView = self.attachment?.items.first as? UIView {
                        let path = UIBezierPath()
                        path.moveToPoint(self.attachment!.anchorPoint)
                        path.addLineToPoint(attacheView.center)
                        self.gameView.setPath(path, named: PathNames.Attachment)
                    }
                }
            }
        }
    }

    
    override func viewDidLoad() {
        super.viewDidLoad()
        animator.addBehavior(dropitBehavior)
    }
    
    struct PathNames {
        static let MiddleBarrier = "Middle Barrier"
        static let Attachment = "Attachment"
    }
    
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let barrierSize = dropSize
        let barrierOrigin = CGPoint(x: gameView.bounds.midX - barrierSize.width / 2, y: gameView.bounds.midY - barrierSize.height / 2)
        //設(shè)置圓圈的邊界
        let path = UIBezierPath(ovalInRect: CGRect(origin: barrierOrigin, size: barrierSize))
        dropitBehavior.addBarrier(path, named: PathNames.MiddleBarrier)
        
        gameView.setPath(path, named: PathNames.MiddleBarrier)
    }
    
    //UIDynamicAnimatorDelegate中的方法,當(dāng)動(dòng)畫停止時(shí)
    func dynamicAnimatorDidPause(animator: UIDynamicAnimator) {
        removeCompletedRow()
    }
    
    
    var dropsPerRow = 10
    //設(shè)置方塊的形狀
    var dropSize: CGSize {
        let size = gameView.bounds.width / CGFloat(dropsPerRow)
        return CGSize(width: size, height: size)
    }

    //設(shè)置手勢(shì)
    @IBAction func drop(sender: UITapGestureRecognizer) {
        drop()
    }
    
    var lastDroppedView: UIView?
    
    //掉落方法
    func drop() {
        //設(shè)置方塊的初始位置及大小
        var frame = CGRect(origin: CGPointZero, size: dropSize)
        frame.origin.x = CGFloat.random(dropsPerRow) * dropSize.width
        
        //創(chuàng)建方塊視圖,并設(shè)置其顏色
        let dropView = UIView(frame: frame)
        dropView.backgroundColor = UIColor.random
        
        lastDroppedView = dropView
        
        dropitBehavior.addDrop(dropView)
    }
    
    
    @IBAction func grabDrop(sender: UIPanGestureRecognizer) {
        let gesturePoint = sender.locationInView(gameView)
        
        switch sender.state {
        case .Began:
            if let viewToAttachTo = lastDroppedView {
                attachment = UIAttachmentBehavior(item: viewToAttachTo, attachedToAnchor: gesturePoint)
                lastDroppedView = nil
            }
        case .Changed:
            attachment?.anchorPoint = gesturePoint
        case .Ended:
            attachment = nil
        default: break
        }
        
    }
    
    //當(dāng)滿行后消除方塊
    func removeCompletedRow() {
        var dropsToRemove = [UIView]()
        var dropFrame = CGRect(x: 0, y: gameView.frame.maxY, width: dropSize.width, height: dropSize.height)
        
        repeat {
            dropFrame.origin.y -= dropSize.height
            dropFrame.origin.x = 0
            var dropsFound = [UIView]()
            var rowIsComplete = true
            for _ in 0 ..< dropsPerRow {
                if let hitView = gameView.hitTest(CGPoint(x: dropFrame.midX, y: dropFrame.midY), withEvent: nil) {
                    if hitView.superview == gameView {
                        dropsFound.append(hitView)
                    } else {
                        rowIsComplete = false
                    }
                }
                dropFrame.origin.x += dropSize.width            }
            if rowIsComplete {
                dropsToRemove += dropsFound
            }
        } while dropsToRemove.count == 0 && dropFrame.origin.y > 0
        
        for drop in dropsToRemove {
            dropitBehavior.removeDrop(drop)
        }
    }

}

private extension CGFloat {
    static func random(max:Int) -> CGFloat {
        return CGFloat(arc4random() % UInt32(max))
    }
}

private extension UIColor {
    class var random:UIColor {
        switch arc4random() % 5 {
        case 0: return UIColor.greenColor()
        case 1: return UIColor.blueColor()
        case 2: return UIColor.orangeColor()
        case 3: return UIColor.redColor()
        case 4: return UIColor.purpleColor()
        default: return UIColor.blackColor()
        }
    }
}
import UIKit

class dropitViewController: UIViewController,UIDynamicAnimatorDelegate {

    @IBOutlet weak var gameView: BezierPathsView!
    
    //創(chuàng)建DynamicAnimator
    lazy var animator: UIDynamicAnimator = {
        let lazilyCreatedDynamicAnimator = UIDynamicAnimator(referenceView: self.gameView)
        lazilyCreatedDynamicAnimator.delegate = self
        return lazilyCreatedDynamicAnimator
    }()
    
    //創(chuàng)建集成了三個(gè)Behavior的DropBehavior的實(shí)例
    var dropitBehavior = DropBehavior()
    
    var attachment: UIAttachmentBehavior? {
        willSet {
            animator.removeBehavior(attachment!)
            gameView.setPath(nil, named: PathNames.Attachment)
        }
        didSet {
            if attachment != nil {
                animator.addBehavior(attachment!)
                attachment?.action = { [unowned self] in
                    if let attacheView = self.attachment?.items.first as? UIView {
                        let path = UIBezierPath()
                        path.moveToPoint(self.attachment!.anchorPoint)
                        path.addLineToPoint(attacheView.center)
                        self.gameView.setPath(path, named: PathNames.Attachment)
                    }
                }
            }
        }
    }

    
    override func viewDidLoad() {
        super.viewDidLoad()
        animator.addBehavior(dropitBehavior)
    }
    
    struct PathNames {
        static let MiddleBarrier = "Middle Barrier"
        static let Attachment = "Attachment"
    }
    
    
    override func viewDidLayoutSubviews() {
        super.viewDidLayoutSubviews()
        let barrierSize = dropSize
        let barrierOrigin = CGPoint(x: gameView.bounds.midX - barrierSize.width / 2, y: gameView.bounds.midY - barrierSize.height / 2)
        //設(shè)置圓圈的邊界
        let path = UIBezierPath(ovalInRect: CGRect(origin: barrierOrigin, size: barrierSize))
        dropitBehavior.addBarrier(path, named: PathNames.MiddleBarrier)
        
        gameView.setPath(path, named: PathNames.MiddleBarrier)
    }
    
    //UIDynamicAnimatorDelegate中的方法,當(dāng)動(dòng)畫停止時(shí)
    func dynamicAnimatorDidPause(animator: UIDynamicAnimator) {
        removeCompletedRow()
    }
    
    
    var dropsPerRow = 10
    //設(shè)置方塊的形狀
    var dropSize: CGSize {
        let size = gameView.bounds.width / CGFloat(dropsPerRow)
        return CGSize(width: size, height: size)
    }

    //設(shè)置手勢(shì)
    @IBAction func drop(sender: UITapGestureRecognizer) {
        drop()
    }
    
    var lastDroppedView: UIView?
    
    //掉落方法
    func drop() {
        //設(shè)置方塊的初始位置及大小
        var frame = CGRect(origin: CGPointZero, size: dropSize)
        frame.origin.x = CGFloat.random(dropsPerRow) * dropSize.width
        
        //創(chuàng)建方塊視圖,并設(shè)置其顏色
        let dropView = UIView(frame: frame)
        dropView.backgroundColor = UIColor.random
        
        lastDroppedView = dropView
        
        dropitBehavior.addDrop(dropView)
    }
    
    
    @IBAction func grabDrop(sender: UIPanGestureRecognizer) {
        let gesturePoint = sender.locationInView(gameView)
        
        switch sender.state {
        case .Began:
            if let viewToAttachTo = lastDroppedView {
                attachment = UIAttachmentBehavior(item: viewToAttachTo, attachedToAnchor: gesturePoint)
                lastDroppedView = nil
            }
        case .Changed:
            attachment?.anchorPoint = gesturePoint
        case .Ended:
            attachment = nil
        default: break
        }
        
    }
    
    //當(dāng)滿行后消除方塊
    func removeCompletedRow() {
        var dropsToRemove = [UIView]()
        var dropFrame = CGRect(x: 0, y: gameView.frame.maxY, width: dropSize.width, height: dropSize.height)
        
        repeat {
            dropFrame.origin.y -= dropSize.height
            dropFrame.origin.x = 0
            var dropsFound = [UIView]()
            var rowIsComplete = true
            for _ in 0 ..< dropsPerRow {
                if let hitView = gameView.hitTest(CGPoint(x: dropFrame.midX, y: dropFrame.midY), withEvent: nil) {
                    if hitView.superview == gameView {
                        dropsFound.append(hitView)
                    } else {
                        rowIsComplete = false
                    }
                }
                dropFrame.origin.x += dropSize.width            }
            if rowIsComplete {
                dropsToRemove += dropsFound
            }
        } while dropsToRemove.count == 0 && dropFrame.origin.y > 0
        
        for drop in dropsToRemove {
            dropitBehavior.removeDrop(drop)
        }
    }

}

private extension CGFloat {
    static func random(max:Int) -> CGFloat {
        return CGFloat(arc4random() % UInt32(max))
    }
}

private extension UIColor {
    class var random:UIColor {
        switch arc4random() % 5 {
        case 0: return UIColor.greenColor()
        case 1: return UIColor.blueColor()
        case 2: return UIColor.orangeColor()
        case 3: return UIColor.redColor()
        case 4: return UIColor.purpleColor()
        default: return UIColor.blackColor()
        }
    }
}

import UIKit

class BezierPathsView: UIView {

    private var bezierPath = [String: UIBezierPath]()
    
    func setPath(path: UIBezierPath?, named name: String) {
        bezierPath[name] = path
        setNeedsDisplay()
    }
    
    override func drawRect(rect: CGRect) {
        for (_,path) in bezierPath {
            path.stroke()
        }
    }

}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市慧瘤,隨后出現(xiàn)的幾起案子环凿,更是在濱河造成了極大的恐慌米死,老刑警劉巖榆鼠,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)口予,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)涕侈,“玉大人苹威,你說(shuō)我怎么就攤上這事〖菪祝” “怎么了牙甫?”我有些...
    開封第一講書人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)调违。 經(jīng)常有香客問(wèn)我窟哺,道長(zhǎng),這世上最難降的妖魔是什么技肩? 我笑而不...
    開封第一講書人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任且轨,我火速辦了婚禮,結(jié)果婚禮上虚婿,老公的妹妹穿的比我還像新娘旋奢。我一直安慰自己,他們只是感情好然痊,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開白布至朗。 她就那樣靜靜地躺著,像睡著了一般剧浸。 火紅的嫁衣襯著肌膚如雪锹引。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 49,079評(píng)論 1 285
  • 那天唆香,我揣著相機(jī)與錄音嫌变,去河邊找鬼。 笑死躬它,一個(gè)胖子當(dāng)著我的面吹牛腾啥,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播冯吓,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開眼倘待,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了桑谍?” 一聲冷哼從身側(cè)響起延柠,我...
    開封第一講書人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎锣披,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡雹仿,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年增热,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片胧辽。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡峻仇,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出邑商,到底是詐尸還是另有隱情摄咆,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布人断,位于F島的核電站吭从,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏恶迈。R本人自食惡果不足惜涩金,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望暇仲。 院中可真熱鬧步做,春花似錦、人聲如沸奈附。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)斥滤。三九已至讼载,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間中跌,已是汗流浹背咨堤。 一陣腳步聲響...
    開封第一講書人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留漩符,地道東北人一喘。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像嗜暴,于是被迫代替她去往敵國(guó)和親凸克。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 本文中所有代碼演示均有GitHub源碼闷沥,點(diǎn)擊下載 UIDynamic簡(jiǎn)介 簡(jiǎn)介:UIKit動(dòng)力學(xué)最大的特點(diǎn)是將現(xiàn)實(shí)...
    si1ence閱讀 10,203評(píng)論 8 79
  • 動(dòng)畫是通過(guò)一系列靜態(tài)圖片(幀)快速顯示來(lái)模擬動(dòng)作和形狀的變化過(guò)程舆逃。 在iOS中蚂维,創(chuàng)建基礎(chǔ)動(dòng)畫很簡(jiǎn)單戳粒,只需要利用UI...
    Andy_Ron閱讀 1,592評(píng)論 0 8
  • 婦女們專享的節(jié)日到了,我這個(gè)攝影師開始蠢蠢欲動(dòng)虫啥,準(zhǔn)備尾隨花枝招展的美女蔚约,開始一番驚天動(dòng)地的創(chuàng)作⊥孔眩《八局之聲》小微們...
    苛娃閱讀 929評(píng)論 4 1
  • 以下3則故事评雌,道出了習(xí)得一項(xiàng)技能的三種狀態(tài):從一無(wú)所知到有所了解树枫,從多方求證到小心嘗試,從刻意練習(xí)到熟能生巧景东。 0...
    葉子俠閱讀 713評(píng)論 0 0
  • 很多時(shí)候你準(zhǔn)備丟了"全世界"走向某個(gè)人,走近了發(fā)現(xiàn)那個(gè)人把你丟了曲初。 晚晴一直記得他說(shuō)他會(huì)一直都在体谒,可是卻不是的。 ...
    TotoroWiki閱讀 864評(píng)論 5 1