狠狠撸

狠狠撸Share a Scribd company logo
Standford 2015 iOS讀書會
week4
1. Protocols and Delegation, Gestures
2. Multiple MVCs
彼得潘
Protocols and Delegation,
Gestures
@IBDesignable
在storyboard顯?示客製化的UI元件
@IBDesignable
class FaceView: UIView {
@IBInspectable
@IBInspectable var scale:CGFloat = 0.9 {
didSet {
setNeedsDisplay()
}
}
@IBInspectable var lineWidth:CGFloat = 3 {
didSet {
setNeedsDisplay()
}
}
@IBInspectable var color:UIColor = UIColor.blueColor() {
didSet {
setNeedsDisplay()
}
}
在storyboard增加元件的設定欄位
?支援的欄位型別:
booleans, strings, numbers
CGPoint, CGSize, CGRect, UIColor, NSRange,
UIImage
var happiness:Int = 50 {
didSet {
happiness = min(max(happiness, 0), 100)
updateUI()
}
}
在property observer裡修改property,
不會觸發observer再次被呼叫
升級原有型別能?力的
extension
? computed property。(不?支援stored property)
? ?方法
? initializer
? subscript
? 遵從protocol,定義protocol裡宣告的?方法屬性
? nested type
升級原有型別能?力的
extension
出?一張嘴,只宣告不定義的
protocol
可宣告?方法,computed property,
subscript,initializer
get?一定要有,set可有可無
class, struct , enum可實作protocol
出?一張嘴,只宣告不定義的
protocol
出?一張嘴,只宣告不定義的
protocol
要?用 as!
宣告遵從多個protocol的變數
protocol Idol {
func sing()
}
protocol Artist {
func paint()
}
var man:Idol!
var woman:protocol<Idol, Artist>!
不?一定要定義的optional
要加上@objc 和import Foundation
import Foundation
@objc protocol Idol {
func sing()
func run()
optional var money:Double {
get
}
optional func playPiano() -> String
}
不?一定要定義的optional
加了optional的protocol只有class可以遵從
此時class也要加上@objc
@objc class Baby:Idol {
func sing() {
}
func run() {
}
func playPiano() -> String {
return "hi"
}
}
var cuteBaby:Idol = Baby()
cuteBaby.playPiano?()
protocol
protocol
實作protocol的init要加上required
(因為subclass可能沒有繼承init)
Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs
Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs
demo
protocol FaceViewDataSource:class {
func smilinessForFaceView(sender:FaceView) -> Double?
}
delegate的?方法常常會將?自?己當參數?
代理?人可依此做不同的處理?
ex: smilinessForFaceView的sender
weak var dataSource:FaceViewDataSource?
weak只能作?用於物件,所以要加class
let smiliness = self.dataSource?.smilinessForFaceView(self) ?? 0
let smilePath = bezierPathForSmile(smiliness)
遇nil即臨陣脫逃的
optional chaining
optional chaining的回傳結果也會是optional
遇nil即臨陣脫逃的optional chaining
利用optional binding判斷可能為nil的cuteBaby和eatFood
定義Food類別和Baby類別
遇nil即臨陣脫逃的optional chaining
利用optional chaining在function eat回傳的Food存取name
利用optional chaining在optional的cuteBaby上呼叫eat function
遇nil即臨陣脫逃的optional chaining
透過optional chaining存取的age也會是optional,不能直接做加法運算
遇nil即臨陣脫逃的optional chaining
dog1當初宣告時不是optional,不用加?存取下一層的food
dog1並非宣告為optional,此生注定和!無緣
變出預設值的雙重問號
當age等於nil時,一律回覆18歲
當age為nil時,回傳雙重問號右邊的預設值18
demo
func smilinessForFaceView(sender: FaceView) -> Double? {
return Double(self.happiness - 50)/50
}
class HappinessViewController: UIViewController, FaceViewDataSource {
@IBOutlet weak var faceView: FaceView! {
didSet {
self.faceView.dataSource = self
}
}
當faceView連結設定時,設定dataSource為self
func updateUI() {
faceView.setNeedsDisplay()
}
cmd + shift + o
開啟open quickly視窗
gesture
UITapGestureRecognizer
UISwipeGestureRecognizer
UIPanGestureRecognizer
UIPinchGestureRecognizer
UIRotationGestureRecognizer
UILongPressGestureRecognizer
UIScreenEdgePanGestureRecognizer
類似UIPanGestureRecognizer,但限制?手勢須從螢幕邊緣開始
使?用gesture
1.加gesture加到作?用的view上
2.設定gesture發?生時觸發的method
驳别蝉迟耻谤别触发的?方法
驳别蝉迟耻谤别触发的?方法實例
不同gesture包含
不同的資訊
demo
func pan(gesture:UIPanGestureRecognizer) {
switch gesture.state {
case .Changed:
fallthrough
case .Ended:
let translation = gesture.translationInView(blueView)
println("translation (translation)")
gesture.setTranslation(CGPointZero, inView:blueView)
default:
break
}
}
觀察呼叫gesture.setTranslation和沒有呼叫gesture.setTranslation的差別
利?用pan移動view:?方法1
func pan(gesture:UIPanGestureRecognizer) {
switch gesture.state {
case .Began:
originalCenter = blueView.center
case .Changed:
fallthrough
case .Ended:
let translation = gesture.translationInView(blueView)
blueView.center = CGPointMake(originalCenter.x +
translation.x,
originalCenter.y + translation.y);
default:
break
}
}
class ViewController: UIViewController {
var originalCenter:CGPoint!
利?用pan移動view:?方法2
func pan(gesture:UIPanGestureRecognizer) {
switch gesture.state {
case .Changed:
fallthrough
case .Ended:
let translation = gesture.translationInView(blueView)
let originalCenter = blueView.center
blueView.center = CGPointMake(originalCenter.x +
translation.x,
originalCenter.y + translation.y);
gesture.setTranslation(CGPointZero, inView:blueView)
default:
break
}
}
pan gesture
var minimumNumberOfTouches: Int // default is 1. the minimum
number of touches required to match
var maximumNumberOfTouches: Int // default is UINT_MAX. the
maximum number of touches that can be down
standford demo
func scale(gesture:UIPinchGestureRecognizer) {
scale = scale * gesture.scale
gesture.scale = 1
}
@IBOutlet weak var faceView: FaceView! {
didSet {
self.faceView.dataSource = self
self.faceView.addGestureRecognizer(UIPinchGestureRecognizer(target:
self.faceView, action: "scale:"))
}
}
从蝉迟辞谤测产辞补谤诲加驳别蝉迟耻谤别
从蝉迟辞谤测产辞补谤诲加驳别蝉迟耻谤别
private struct Constants {
static let HappinessGestureScale:CGFloat = 4
}
@IBAction func changeHappiness(sender: UIPanGestureRecognizer) {
switch sender.state {
case .Ended:
fallthrough
case .Changed:
let translation = sender.translationInView(faceView)
let happinessChange = -Int(translation.y /
Constants.HappinessGestureScale)
if happinessChange != 0 {
happiness += happinessChange
sender.setTranslation(CGPointZero, inView: faceView)
}
default:
break
}
}
?手指往下 -> 不開?心
?手指往上 -> 開?心
模擬器pinch
按住option後,按觸控版移動
https://developer.apple.com/library/mac/documentation/IDEs/
Conceptual/iOS_Simulator_Guide/
InteractingwiththeiOSSimulator.html
Multiple MVCs
第五個tab: more
For iPad
iPhone只有6 plus的landscape會分割畫?面
iPhone模式下的問題
UITabBarController & UINavigationController的結合
Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs
Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs
Show: 1.有navigation controller?用push?
2. 沒有navigation controller?用modal
Show Detail: 1.有Split View Controller顯?示detail?
(Split View Controller若搭配navigation controller,
在iPhone會採?用push顯?示detail,除了6 plus landscape例外)
2. 沒有Split View Controller?用modal
func performSegueWithIdenti?er(identi?er:
String, sender: AnyObject?)
從程式觸發切換到另?一個controller畫?面
Once the MVC is prepared, it should run on its own power
(only using delegation to talk back)
It is crucial to understand that this preparation is happening
BEFORE outlets get set!!
防?止segue發?生
func shouldPerformSegueWithIdenti?er(identi?er: String?,
sender: AnyObject?) -> Bool
?比較Reset to Suggested Constraints & Add Missing
Constraints
?自动缩放字型?大?小
Split View Controller的iPhone
問題
解法: master加上navigation
controller
func updateUI() {
faceView.setNeedsDisplay()
}
func updateUI() {
faceView?.setNeedsDisplay()
}
修正nil crash問題
optional chaining
笑脸被产补谤档到了
修正笑脸档到问题
颈笔补诲版笑脸加标题
颈笔补诲版笑脸加标题
Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs
property observer的override
保留?父類別的observer
property observer的override
保留?父類別的observer
property observer的override
問題: history只有?一筆資料
因為DiagnosedHappinessViewController會重新?生成
問題: history只有?一筆資料
利?用user defaults儲存
private let defaults = NSUserDefaults.standardUserDefaults()
var diagnosticHisotry:[Int] {
get {
return defaults.objectForKey(History.DefaultsKey) as?
[Int] ?? []
}
set {
defaults.setObject(newValue, forKey: History.DefaultsKey)
}
}
修正iPhone Popover 全螢
幕的問題
修正iPhone Popover 全螢
幕的問題
func
adaptivePresentationStyleForPresentationController(controller:
UIPresentationController) -> UIModalPresentationStyle {
return UIModalPresentationStyle.None
}
class DiagnosedHappinessViewController : HappinessViewController,
UIPopoverPresentationControllerDelegate
實作UIPopoverPresentationControllerDelegate的?方法
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let identifier = segue.identifier {
switch identifier {
case History.SegueIdentifier:
if let tvc = segue.destinationViewController as? TextViewController {
if let ppc = tvc.popoverPresentationController {
ppc.delegate = self
}
tvc.text = "(diagnosticHisotry)"
}
default:
break
}
}
}
修正iPhone Popover 全螢
幕的問題
修正iPhone Popover 全螢
幕的問題
調整pop over的size
override var preferredContentSize:CGSize {
get {
if textView != nil && presentingViewController != nil {
let size = textView.sizeThatFits(presentingViewController!.view.bounds.size)
println("size (size)")
return textView.sizeThatFits(presentingViewController!.view.bounds.size)
}
else {
return super.preferredContentSize
}
}
set {
super.preferredContentSize = newValue
}
}
定義UIViewController的preferredContentSize property
調整pop over的size

More Related Content

Standford 2015 week4: 1.Protocols and Delegation, Gestures 2. Multiple MVCs