Standford 2015 week6
Transcript of Standford 2015 week6
![Page 1: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/1.jpg)
Standford 2015 iOS讀書會 week6
1. Multithreading 2. Table View
彼得潘
![Page 2: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/2.jpg)
Main Queue: serial queue,⼀一次從queue取出⼀一個function執⾏行
UI相關動作⼀一定要在main queue執⾏行
Grand Central Dispatch
![Page 3: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/3.jpg)
![Page 4: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/4.jpg)
dispatch_async & dispatch_sync
async: return after task is added to queue
sync: return after task is done
![Page 5: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/5.jpg)
![Page 6: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/6.jpg)
serial & concurrent queue
https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html
![Page 7: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/7.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/8.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/9.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/10.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/11.jpg)
![Page 12: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/12.jpg)
不在main thread做UI會 ->
Crash ,變慢,奇怪現象
![Page 13: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/13.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/14.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/15.jpg)
建⽴立session
let session = NSURLSession.sharedSession()
let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration())
預設會將抓到的資料存在disk,App重新啟動還會存在
若是抓取size太⼤大的資料不會儲存在disk
![Page 16: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/16.jpg)
建⽴立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](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/17.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/18.jpg)
table
![Page 19: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/19.jpg)
⼀一⾏行,多⾏行輸⼊入需⽤用UITextView
![Page 20: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/20.jpg)
收鍵盤⽅方法⼤大全
1. 在畫⾯面上加⼊入tap gesture 2. 設定return鍵觸發,經由設定Did End On Exit Event或是
delete的textFieldShouldReturn
⽅方法⼀一: resignFirstResponder ⽅方法⼆二: self.view.endEditing(true) ⽅方法三: 設定keyboardDismissMode
觸發⽅方法:
![Page 21: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/21.jpg)
![Page 22: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/22.jpg)
autocapitalizationType: 控制⼤大⼩小寫
![Page 23: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/23.jpg)
observer死掉時,會⾃自動被NSNotificationCenter移除
UITableViewController搭配UITextView和UITextField獲得⾃自動scroll魔⼒力
addObserver不會增加observer的retina count
![Page 24: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/24.jpg)
inputView: 客製化鍵盤,⽐比⽅方將picker設成鍵盤
![Page 25: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/25.jpg)
![Page 26: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/26.jpg)
![Page 27: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/27.jpg)
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](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/28.jpg)
![Page 29: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/29.jpg)
section: 滑動表格時會固定在畫⾯面上⽅方,參考通訊錄App
![Page 30: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/30.jpg)
![Page 31: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/31.jpg)
UITableViewController
view就是tableView
⾃自動連結data source & delegate
如果⾃自⼰己拉的table view要⼿手動連結
static⼀一定要搭配UITableViewController
keyboard auto scroll
![Page 32: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/32.jpg)
不限數量的內容
![Page 33: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/33.jpg)
Dynamic Prototypes
![Page 34: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/34.jpg)
內容⾏行數固定的表格百分之五⼗十的畫⾯面是⾏行數固定的Table
![Page 35: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/35.jpg)
Static Cells只能搭配UITableViewController!
![Page 36: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/36.jpg)
多出來的分隔線?
![Page 37: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/37.jpg)
清除多出來的分隔線: tableFooterView
tableFooterViewtableHeaderView
加了header才能加footer
![Page 38: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/38.jpg)
超級⽐比⼀一⽐比@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](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/39.jpg)
⽅方法⼀一: UITableViewController做child controller
讓整個畫⾯面只有某部分是table的⽅方法
⽅方法⼆二: UITableView做subview
![Page 40: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/40.jpg)
![Page 41: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/41.jpg)
cell reuse: 圖⽚片download問題
圖⽚片完成下載時,cell已被reuse解法: : ⽅方法⼀一:在cell裡儲存url,⽐比對url確認是否顯⽰示 ⽅方法⼆二:定義cell的prepareForReuse,於其中終⽌止下載圖⽚片的動作
![Page 42: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/42.jpg)
![Page 43: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/43.jpg)
![Page 44: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/44.jpg)
cell裡設定IBOutlet & IBAction
IBOutlet連結到cell的程式檔
IBAction連結到controller的程式檔
IBOutlet不能連結到controller的程式檔
![Page 45: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/45.jpg)
在storyboard從cell拉segue時, 可以選selection 或 accessory action (對應Detail Disclosure)
![Page 46: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/46.jpg)
![Page 47: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/47.jpg)
![Page 48: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/48.jpg)
![Page 49: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/49.jpg)
![Page 50: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/50.jpg)
![Page 51: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/51.jpg)
![Page 52: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/52.jpg)
//MARK: - // MARK: - Navigation
![Page 53: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/53.jpg)
font: Headline & Body
![Page 54: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/54.jpg)
cell點選樣式
![Page 55: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/55.jpg)
accessory樣式
![Page 56: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/56.jpg)
動態cell⾼高度
tableView.estimatedRowHeight = tableView.rowHeight tableView.rowHeight = UITableViewAutomaticDimension
![Page 57: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/57.jpg)
表格的多選self.tableView.allowsMultipleSelectionDuringEditing = YES; self.tableView.editing = YES;
![Page 58: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/58.jpg)
表格的delete
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath)
![Page 59: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/59.jpg)
表格cell順序調整
func tableView(tableView: UITableView, canMoveRowAtIndexPath indexPath: NSIndexPath) -> Bool
func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath)
![Page 60: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/60.jpg)
下拉更新的refresh
UITableViewController內建UIRefreshControl, 若是⾃自⼰己加⼊入的UITableView必須另外加上UIRefreshControl
![Page 61: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/61.jpg)
下拉更新的refresh
@IBAction func refresh(sender: AnyObject) { self.refreshControl?.endRefreshing() }
定義下拉更新觸發的method
endRefreshing: 結束更新,表格回到正常狀態
![Page 62: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/62.jpg)
Clear on Appearance
var clearsSelectionOnViewWillAppear: BoolUITableViewController:
設定⾴頁⾯面appear時,原本被select的cell是否取消選取,勾選表⽰示取消選取
⺫⽬目前在storyboard設定無效,預設會是取消選取, 若想改成不選取,必須另外從程式將clearsSelectionOnViewWillAppear設成false
![Page 63: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/63.jpg)
固定某個元件, 不隨表格scroll
⽅方法⼀一: 將table加到controller的view上
⽅方法⼆二: 將UITableViewController當成child controller, 可利⽤用storyboard的Container View
![Page 64: Standford 2015 week6](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/64.jpg)
固定某個元件, 不隨表格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](https://reader034.fdocuments.net/reader034/viewer/2022042602/55b6deafbb61ebed588b4837/html5/thumbnails/65.jpg)
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/