standford 2015 week6

65
Standford 2015 iOS讀書會 week6 1. Multithreading 2. Table View 彼得潘

Upload: -pan

Post on 28-Jul-2015

388 views

Category:

Mobile


3 download

TRANSCRIPT

Page 1: Standford 2015 week6

Standford 2015 iOS讀書會 week6

1. Multithreading 2. Table View

彼得潘

Page 2: Standford 2015 week6

Main Queue: serial queue,⼀一次從queue取出⼀一個function執⾏行

UI相關動作⼀一定要在main queue執⾏行

Grand Central Dispatch

Page 3: Standford 2015 week6
Page 4: Standford 2015 week6

dispatch_async & dispatch_sync

async: return after task is added to queue

sync: return after task is done

Page 5: Standford 2015 week6
Page 6: Standford 2015 week6

serial & concurrent queue

https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html

Page 7: Standford 2015 week6

demo var number1 = 0 var number2 = 0 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. let queue = dispatch_queue_create("Queue", DISPATCH_QUEUE_SERIAL) dispatch_async(queue, { () -> Void in for i in 1...10 { self.number1++ NSThread.sleepForTimeInterval(0.1) if i == 10 { println("number1 \(self.number1) number2 \(self.number2)")

} } }) println("dispatch_async1") dispatch_async(queue, { () -> Void in for i in 1...10 { self.number2++ } }) println("dispatch_async2")

}

dispatch_async1 dispatch_async2 number1 10 number2 0

serial: FIFO

Page 8: Standford 2015 week6

demo var number1 = 0 var number2 = 0 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. let queue = dispatch_queue_create("Queue", DISPATCH_QUEUE_CONCURRENT) dispatch_async(queue, { () -> Void in for i in 1...10 { self.number1++ NSThread.sleepForTimeInterval(0.1) if i == 10 { println("number1 \(self.number1) number2 \(self.number2)")

} } }) println("dispatch_async1") dispatch_async(queue, { () -> Void in for i in 1...10 { self.number2++ } }) println("dispatch_async2")

}

dispatch_async1 dispatch_async2 number1 10 number2 10

Page 9: Standford 2015 week6

demo var number1 = 0 var number2 = 0 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. let queue = dispatch_queue_create("Queue", DISPATCH_QUEUE_SERIAL) dispatch_sync(queue, { () -> Void in for i in 1...10 { self.number1++ NSThread.sleepForTimeInterval(0.1) if i == 10 { println("number1 \(self.number1) number2 \(self.number2)")

} } }) println("dispatch_sync1") dispatch_sync(queue, { () -> Void in for i in 1...10 { self.number2++ } }) println("dispatch_sync2")

}

number1 10 number2 0dispatch_sync1dispatch_sync2

Page 10: Standford 2015 week6

demo var number1 = 0 var number2 = 0 override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. let queue = dispatch_queue_create("Queue", DISPATCH_QUEUE_CONCURRENT) dispatch_sync(queue, { () -> Void in for i in 1...10 { self.number1++ NSThread.sleepForTimeInterval(0.1) if i == 10 { println("number1 \(self.number1) number2 \(self.number2)")

} } }) println("dispatch_sync1") dispatch_sync(queue, { () -> Void in for i in 1...10 { self.number2++ } }) println("dispatch_sync2")

}

number1 10 number2 0dispatch_sync1dispatch_sync2

Page 11: Standford 2015 week6
Page 12: Standford 2015 week6

不在main thread做UI會 ->

Crash ,變慢,奇怪現象

Page 13: Standford 2015 week6

NSURLSessionfunc testDownload() { let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) if let url = NSURL(string: "http://res.cloudinary.com/hrscywv4p/image/upload/c_limit,f_auto,h_3000,q_80,w_1200/v1/271374/http_s3.amazonaws.com_feather-files-aviary-prod-us-east-1_f5da8ea5e_2015-03-12_723490bbf79e44a788f5cd2516fefd46_myvzle.jpg") { let request = NSURLRequest(URL: url) let task = session.downloadTaskWithRequest(request, completionHandler: { (localUrl, response, err) -> Void in let data = NSData(contentsOfURL: localUrl) let image = UIImage(data: data!) let imageView = UIImageView(image: image) self.view.addSubview(imageView) println("add image")

}) task.resume() } } 圖⽚片過⼀一段時間才出現

Page 14: Standford 2015 week6

NSURLSession func testDownload() { let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) if let url = NSURL(string: "http://res.cloudinary.com/hrscywv4p/image/upload/c_limit,f_auto,h_3000,q_80,w_1200/v1/271374/http_s3.amazonaws.com_feather-files-aviary-prod-us-east-1_f5da8ea5e_2015-03-12_723490bbf79e44a788f5cd2516fefd46_myvzle.jpg") { let request = NSURLRequest(URL: url) let task = session.downloadTaskWithRequest(request, completionHandler: { (localUrl, response, err) -> Void in let data = NSData(contentsOfURL: localUrl) let image = UIImage(data: data!) dispatch_async(dispatch_get_main_queue(), { () -> Void in let imageView = UIImageView(image: image) self.view.addSubview(imageView)

}) }) task.resume() } }

Page 15: Standford 2015 week6

建⽴立session

let session = NSURLSession.sharedSession()

let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())

預設會將抓到的資料存在disk,App重新啟動還會存在

若是抓取size太⼤大的資料不會儲存在disk

Page 16: Standford 2015 week6

建⽴立task

let task = session.dataTaskWithURL(url, completionHandler: { (data, response, err) -> Void in let image = UIImage(data: data!) dispatch_async(dispatch_get_main_queue(), { () -> Void in let imageView = UIImageView(image: image) self.view.addSubview(imageView) }) })

let task = session.downloadTaskWithRequest(request, completionHandler: { (localUrl, response, err) -> Void in let data = NSData(contentsOfURL: localUrl) let image = UIImage(data: data!) dispatch_async(dispatch_get_main_queue(), { () -> Void in let imageView = UIImageView(image: image) self.view.addSubview(imageView)

}) })

Page 17: Standford 2015 week6

private func fetchImage() { if let url = imageURL { spinner?.startAnimating() let qos = Int(QOS_CLASS_USER_INITIATED.value) dispatch_async(dispatch_get_global_queue(qos, 0)) { () -> Void in let imageData = NSData(contentsOfURL: url) // this blocks the thread it is on dispatch_async(dispatch_get_main_queue()) { // only do something with this image // if the url we fetched is the current imageURL we want // (that might have changed while we were off fetching this one) if url == self.imageURL { // the variable "url" is capture from above if imageData != nil { // this might be a waste of time if our MVC is out of action now // which it might be if someone hit the Back button // or otherwise removed us from split view or navigation controller // while we were off fetching the image self.image = UIImage(data: imageData!) } else { self.image = nil } } } } } }

closure裡要⽤用self.image,不能只⽤用imageif url == self.imageURL : 判斷是否是⺫⽬目前要顯⽰示的圖⽚片

⽤用weak , unowned 設定self ?

Page 18: Standford 2015 week6

table

Page 19: Standford 2015 week6

⼀一⾏行,多⾏行輸⼊入需⽤用UITextView

Page 20: Standford 2015 week6

收鍵盤⽅方法⼤大全

1. 在畫⾯面上加⼊入tap gesture 2. 設定return鍵觸發,經由設定Did End On Exit Event或是

delete的textFieldShouldReturn

⽅方法⼀一: resignFirstResponder ⽅方法⼆二: self.view.endEditing(true) ⽅方法三: 設定keyboardDismissMode

觸發⽅方法:

Page 21: Standford 2015 week6
Page 22: Standford 2015 week6

autocapitalizationType: 控制⼤大⼩小寫

Page 23: Standford 2015 week6

observer死掉時,會⾃自動被NSNotificationCenter移除

UITableViewController搭配UITextView和UITextField獲得⾃自動scroll魔⼒力

addObserver不會增加observer的retina count

Page 24: Standford 2015 week6

inputView: 客製化鍵盤,⽐比⽅方將picker設成鍵盤

Page 25: Standford 2015 week6
Page 26: Standford 2015 week6
Page 27: Standford 2015 week6

UITableViewDataSource’s tableView(UITableView, cellForRowAtIndexPath: NSIndexPath)

UITableViewDataSource’s tableView(UITableView, titleForFooterInSection: Int)

UITableViewDataSource’s tableView(UITableView, titleForHeaderInSection: Int)

var tableFooterView: UIView

var tableHeaderView: UIView

Page 28: Standford 2015 week6
Page 29: Standford 2015 week6

section: 滑動表格時會固定在畫⾯面上⽅方,參考通訊錄App

Page 30: Standford 2015 week6
Page 31: Standford 2015 week6

UITableViewController

view就是tableView

⾃自動連結data source & delegate

如果⾃自⼰己拉的table view要⼿手動連結

static⼀一定要搭配UITableViewController

keyboard auto scroll

Page 32: Standford 2015 week6

不限數量的內容

Page 33: Standford 2015 week6

Dynamic Prototypes

Page 34: Standford 2015 week6

內容⾏行數固定的表格百分之五⼗十的畫⾯面是⾏行數固定的Table

Page 35: Standford 2015 week6

Static Cells只能搭配UITableViewController!

Page 36: Standford 2015 week6

多出來的分隔線?

Page 37: Standford 2015 week6

清除多出來的分隔線: tableFooterView

tableFooterViewtableHeaderView

加了header才能加footer

Page 38: Standford 2015 week6

超級⽐比⼀一⽐比@property (nonatomic, retain) UIView *tableHeaderView;

@property (nonatomic, retain) UIView *tableFooterView;

- (UITableViewHeaderFooterView *)headerViewForSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);

- (UITableViewHeaderFooterView *)footerViewForSection:(NSInteger)section NS_AVAILABLE_IOS(6_0);

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section;

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section;

Page 39: Standford 2015 week6

⽅方法⼀一: UITableViewController做child controller

讓整個畫⾯面只有某部分是table的⽅方法

⽅方法⼆二: UITableView做subview

Page 40: Standford 2015 week6
Page 41: Standford 2015 week6

cell reuse: 圖⽚片download問題

圖⽚片完成下載時,cell已被reuse解法: : ⽅方法⼀一:在cell裡儲存url,⽐比對url確認是否顯⽰示 ⽅方法⼆二:定義cell的prepareForReuse,於其中終⽌止下載圖⽚片的動作

Page 42: Standford 2015 week6
Page 43: Standford 2015 week6
Page 44: Standford 2015 week6

cell裡設定IBOutlet & IBAction

IBOutlet連結到cell的程式檔

IBAction連結到controller的程式檔

IBOutlet不能連結到controller的程式檔

Page 45: Standford 2015 week6

在storyboard從cell拉segue時, 可以選selection 或 accessory action (對應Detail Disclosure)

Page 46: Standford 2015 week6
Page 47: Standford 2015 week6
Page 48: Standford 2015 week6
Page 49: Standford 2015 week6
Page 50: Standford 2015 week6
Page 51: Standford 2015 week6
Page 52: Standford 2015 week6

//MARK: - // MARK: - Navigation

Page 53: Standford 2015 week6

font: Headline & Body

Page 54: Standford 2015 week6

cell點選樣式

Page 55: Standford 2015 week6

accessory樣式

Page 56: Standford 2015 week6

動態cell⾼高度

tableView.estimatedRowHeight = tableView.rowHeight tableView.rowHeight = UITableViewAutomaticDimension

Page 57: Standford 2015 week6

表格的多選self.tableView.allowsMultipleSelectionDuringEditing = YES; self.tableView.editing = YES;

Page 58: Standford 2015 week6

表格的delete

func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)

Page 59: Standford 2015 week6

表格cell順序調整

func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool

func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)

Page 60: Standford 2015 week6

下拉更新的refresh

UITableViewController內建UIRefreshControl, 若是⾃自⼰己加⼊入的UITableView必須另外加上UIRefreshControl

Page 61: Standford 2015 week6

下拉更新的refresh

@IBAction func refresh(sender: AnyObject) { self.refreshControl?.endRefreshing() }

定義下拉更新觸發的method

endRefreshing: 結束更新,表格回到正常狀態

Page 62: Standford 2015 week6

Clear on Appearance

var clearsSelectionOnViewWillAppear: BoolUITableViewController:

設定⾴頁⾯面appear時,原本被select的cell是否取消選取,勾選表⽰示取消選取

⺫⽬目前在storyboard設定無效,預設會是取消選取, 若想改成不選取,必須另外從程式將clearsSelectionOnViewWillAppear設成false

Page 63: Standford 2015 week6

固定某個元件, 不隨表格scroll

⽅方法⼀一: 將table加到controller的view上

⽅方法⼆二: 將UITableViewController當成child controller, 可利⽤用storyboard的Container View

Page 64: Standford 2015 week6

固定某個元件, 不隨表格scroll

⽅方法三: 將元件加到UITableViewController的view上, 實作scrollViewDidScroll調整元件位置

override func scrollViewDidScroll(scrollView: UIScrollView) { var frame = self.blueView.frame frame.origin.y = 10 + scrollView.contentOffset.y self.blueView.frame = frame }

override func scrollViewDidScroll(scrollView: UIScrollView) { var frame = self.blueView.frame frame.origin.y = 10 + scrollView.contentOffset.y + 64 self.blueView.frame = frame }

當有透明的nav bar時

Page 65: Standford 2015 week6

cell swipe顯⽰示多個button

func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)

func tableView(tableView: UITableView, editActionsForRowAtIndexPath indexPath: NSIndexPath) -> [AnyObject]?

http://www.codebuddies.de/2015/03/14/swipeable-cells-in-about-5-minutes-swift/