Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Realm Japan hands-on Osaka

Realm Japan hands-on Osaka

Realm Japan hands-on Osaka

9bf923e39671cde83584e3e926296c13?s=128

Kishikawa Katsumi

August 09, 2016
Tweet

Transcript

  1. Realm Hands-on Osaka kk@realm.io

  2. #realm_jp kk@realm.io

  3. Katsumi Kishikawa Realm Inc. kk@realm.io

  4. Realmͷμ΢ϯϩʔυ IUUQTSFBMNJPKQEPDTTXJGUMBUFTUTFDUJPO kk@realm.io

  5. ➙傈⡲׷،فٔ kk@realm.io

  6. kk@realm.io

  7. ➙傈⡲׷،فٔ kk@realm.io HJUIVCDPNLJTIJLBXBLBUTVNJ3FBMN)BOET0O

  8. أٓ؎س kk@realm.io CJUMZ3FBMN)BOET0O

  9. "HFOEB kk@realm.io

  10. Agenda ˖ 㛇劤箟  إحز،حف  ؐؓ٦ىؚٝ،حف  5XJUUFSךة؎يٓ؎ٝ׾邌爙׃ג׫׷ 

    䒷׏䓸׏ג刿倜ָדֹ׷״ֲחׅ׷  鼅䫛׃׋5XFFU׾-JLFדֹ׷״ֲחׅ׷ ˖ 䘔欽箟  5XFFU׾嗚稊דֹ׷״ֲחׅ׷ kk@realm.io
  11. إحز،حف kk@realm.io

  12. إحز،حف ˖ ؽٕس幥׫ؿٖ٦يٙ٦ؙ ˖ $PDPB1PET ˖ $BSUIBHF kk@realm.io

  13. إحز،حف ˖ ؽٕس幥׫ؿٖ٦يٙ٦ؙ ˖ $PDPB1PET ˖ $BSUIBHF kk@realm.io

  14. kk@realm.io

  15. kk@realm.io

  16. kk@realm.io

  17. kk@realm.io

  18. kk@realm.io

  19. 然钠ׅ׷ kk@realm.io import UIKit import RealmSwift @UIApplicationMain class AppDelegate: UIResponder,

    UIApplicationDelegate { var window: UIWindow? func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { let realm = try! Realm() print(realm) return true } }
  20. ؐؓ٦ي،حف kk@realm.io

  21. ؐؓ٦ي،حف kk@realm.io import Foundation import RealmSwift class Tweet: Object {

    dynamic var name = "" dynamic var text = "" dynamic var iconURL = "" dynamic var id = "" dynamic var createdAt = NSDate() }
  22. ؐؓ٦ي،حف kk@realm.io let tweet = Tweet() tweet.name = "test name"

    tweet.text = "test text" try! realm.write { realm.add(tweet) } let tweets = realm.objects(Tweet.self) for tweet in tweets { print(tweet.name) print(tweet.text) print(tweet.createdAt) }
  23. 5XJUUFSךة؎يٓ؎ٝ׾ 邌爙׃ג׫׷ kk@realm.io

  24. kk@realm.io

  25. ة؎يٓ؎ٝ׾邌爙 kk@realm.io import Foundation import RealmSwift class Tweet: Object {

    dynamic var name = "" dynamic var text = "" dynamic var iconURL = "" dynamic var id = "" dynamic var createdAt = NSDate() }
  26. ة؎يٓ؎ٝ׾邌爙 kk@realm.io class Tweet: Object { dynamic var name =

    "" dynamic var text = "" dynamic var iconURL = "" dynamic var id = "" dynamic var createdAt = NSDate() static var dateFormatter: NSDateFormatter { let dateFormatter = NSDateFormatter() dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX") dateFormatter.dateFormat = "EEE MMM dd HH:mm:ss Z yyyy" return dateFormatter } convenience init(tweetDictionary: [String: AnyObject]) { self.init() let user = tweetDictionary["user"] as! [String: AnyObject] name = user["name"] as! String text = tweetDictionary["text"] as! String iconURL = user["profile_image_url_https"] as! String id = tweetDictionary["id_str"] as! String createdAt = Tweet.dateFormatter.dateFromString(tweetDictionary["created_at"] as! String)! } }
  27. ة؎يٓ؎ٝ׾邌爙 kk@realm.io import UIKit class TimelineCell: UITableViewCell { @IBOutlet weak

    var iconView: UIImageView! @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var tweetTextView: UITextView! override func prepareForReuse() { iconView.image = nil nameLabel.text = nil tweetTextView.text = nil } }
  28. Bة؎يٓ؎ٝ׾邌爙 kk@realm.io import UIKit import Accounts import Social import RealmSwift

    class TimelineViewController: UITableViewController { var account: ACAccount? func getHomeTimeline() { let requestURL = NSURL(string: "https://api.twitter.com/1/statuses/home_timeline.json") let request = SLRequest(forServiceType: SLServiceTypeTwitter, requestMethod: .GET, URL: requestURL, parameters: nil) request.account = account request.performRequestWithHandler { (data, response, error) -> Void in if let error = error { self.showAlert(error.localizedDescription) return } do { let results = try NSJSONSerialization.JSONObjectWithData(data, options: []) if let results = results as? NSDictionary { let errors = results["errors"] as! [[String: AnyObject]] let message = errors.last!["message"] as! String self.showAlert(message) return } let timeline = results as! [[String: AnyObject]] let realm = try! Realm() try! realm.write { timeline.forEach { (tweetDictionary) -> () in let tweet = Tweet(tweetDictionary: tweetDictionary) realm.add(tweet) } } } catch let error as NSError { self.showAlert(error.localizedDescription) } } } func showAlert(message: String) { dispatch_async(dispatch_get_main_queue()) { let alertController = UIAlertController(title: "Error", message: message, preferredStyle: .Alert) alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil)) self.presentViewController(alertController, animated: true, completion: nil) } } }
  29. Cة؎يٓ؎ٝ׾邌爙 kk@realm.io override func viewDidLoad() { super.viewDidLoad() let accountStore =

    ACAccountStore() let accountType = accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter) accountStore.requestAccessToAccountsWithType(accountType, options: nil) { (granted, error) -> Void in if granted { let accounts = accountStore.accountsWithAccountType(accountType) if let account = accounts.first as? ACAccount { self.account = account self.getHomeTimeline() } else { self.showAlert("No Twitter account") } } else { self.showAlert("No account access") } } }
  30. Bة؎يٓ؎ٝ׾邌爙 kk@realm.io class TimelineViewController: UITableViewController { var timeline: Results<Tweet>? var

    notificationToken: NotificationToken? var account: ACAccount? ...
  31. Cة؎يٓ؎ٝ׾邌爙 kk@realm.io override func viewDidLoad() { super.viewDidLoad() ... tableView.registerNib(UINib(nibName: "TimelineCell",

    bundle: nil), forCellReuseIdentifier: "timelineCell" tableView.rowHeight = 90 tableView.estimatedRowHeight = 90 let realm = try! Realm() timeline = realm.objects(Tweet).sorted("createdAt", ascending: false) notificationToken = timeline?.addNotificationBlock { [weak self] (change) in switch change { case .Initial(_): self?.tableView.reloadData() case .Update(_, deletions: _, insertions: _, modifications: _): self?.tableView.reloadData() case .Error(_): return } } }
  32. ة؎يٓ؎ٝ׾邌爙 kk@realm.io override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return

    1 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return timeline?.count ?? 0 } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("timelineCell", forIndexPath: indexPath) as! TimelineCell let tweet = timeline![indexPath.row] cell.nameLabel.text = tweet.name cell.tweetTextView.text = tweet.text NSURLSession.sharedSession().dataTaskWithRequest(NSURLRequest(URL: NSURL(string: tweet.iconURL)!)) { (data, response, error) -> Void if let _ = error { return } dispatch_async(dispatch_get_main_queue()) { let image = UIImage(data: data!)! cell.iconView.image = image } }.resume() return cell } override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return UITableViewAutomaticDimension }
  33. ة؎يٓ؎ٝ׾邌爙 kk@realm.io import UIKit import Accounts import Social import RealmSwift

    class TimelineViewController: UITableViewController { var timeline: Results<Tweet>? var notificationToken: NotificationToken? var account: ACAccount? override func viewDidLoad() { super.viewDidLoad() let accountStore = ACAccountStore() let accountType = accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter) accountStore.requestAccessToAccountsWithType(accountType, options: nil) { (granted, error) -> Void in if granted { let accounts = accountStore.accountsWithAccountType(accountType) if let account = accounts.first as? ACAccount { self.account = account self.getHomeTimeline() } else { self.showAlert("No Twitter account") } } else { self.showAlert("No account access") } } tableView.registerNib(UINib(nibName: "TimelineCell", bundle: nil), forCellReuseIdentifier: "timelineCell") tableView.rowHeight = 90 tableView.estimatedRowHeight = 90 let realm = try! Realm() timeline = realm.objects(Tweet).sorted("createdAt", ascending: false) notificationToken = timeline?.addNotificationBlock { [weak self] (change) in switch change { case .Initial(_): self?.tableView.reloadData() case .Update(_, deletions: _, insertions: _, modifications: _): self?.tableView.reloadData() case .Error(_): return } } } func getHomeTimeline() { let requestURL = NSURL(string: "https://api.twitter.com/1/statuses/home_timeline.json") let request = SLRequest(forServiceType: SLServiceTypeTwitter, requestMethod: .GET, URL: requestURL, parameters: nil) request.account = account request.performRequestWithHandler { (data, response, error) -> Void in if let error = error { self.showAlert(error.localizedDescription) return } do { let results = try NSJSONSerialization.JSONObjectWithData(data, options: []) if let results = results as? NSDictionary { let errors = results["errors"] as! [[String: AnyObject]] let message = errors.last!["message"] as! String self.showAlert(message) return } let timeline = results as! [[String: AnyObject]] let realm = try! Realm() try! realm.write { timeline.forEach { (tweetDictionary) -> () in let tweet = Tweet(tweetDictionary: tweetDictionary) realm.add(tweet) } } } catch let error as NSError { self.showAlert(error.localizedDescription) } } } func showAlert(message: String) { dispatch_async(dispatch_get_main_queue()) { let alertController = UIAlertController(title: "Error", message: message, preferredStyle: .Alert) alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil)) self.presentViewController(alertController, animated: true, completion: nil) } } override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return timeline?.count ?? 0 } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("timelineCell", forIndexPath: indexPath) as! TimelineCell let tweet = timeline![indexPath.row] cell.nameLabel.text = tweet.name cell.tweetTextView.text = tweet.text NSURLSession.sharedSession().dataTaskWithRequest(NSURLRequest(URL: NSURL(string: tweet.iconURL)!)) { (data, response, error) -> Void in if let _ = error { return } dispatch_async(dispatch_get_main_queue()) { let image = UIImage(data: data!)! cell.iconView.image = image } }.resume() return cell } override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return UITableViewAutomaticDimension } }
  34. չ䒷׏䓸׏ג刿倜պָ דֹ׷״ֲחׅ׷ kk@realm.io

  35. kk@realm.io

  36. B䒷׏䓸׏ג刿倜 kk@realm.io

  37. C䒷׏䓸׏ג刿倜 kk@realm.io case .Error(_): return } } refreshControl?.addTarget(self, action: #selector(TimelineViewController.refresh(_:)),

    forControlEvents: .ValueChanged) } func refresh(sender: UIRefreshControl) { if let _ = self.account { getHomeTimeline() } } func getHomeTimeline() { let requestURL = NSURL(string: "https://api.twitter.com/1/statuses/home_timeline.json")
  38. D䒷׏䓸׏ג刿倜 kk@realm.io func getHomeTimeline() { let requestURL = NSURL(string: "https://api.twitter.com/1/statuses/home_timeline.json")

    let request = SLRequest(forServiceType: SLServiceTypeTwitter, requestMethod: .GET, URL: requestURL, parameters: nil) request.account = account request.performRequestWithHandler { (data, response, error) -> Void in if let error = error { self.showAlert(error.localizedDescription) return } do { let results = try NSJSONSerialization.JSONObjectWithData(data, options: []) if let results = results as? NSDictionary { let errors = results["errors"] as! [[String: AnyObject]] let message = errors.last!["message"] as! String self.showAlert(message) return } let timeline = results as! [[String: AnyObject]] let realm = try! Realm() try! realm.write { timeline.forEach { (tweetDictionary) -> () in let tweet = Tweet(tweetDictionary: tweetDictionary) realm.add(tweet, update: true) } } } catch let error as NSError { self.showAlert(error.localizedDescription) } dispatch_async(dispatch_get_main_queue()) { self.refreshControl?.endRefreshing() }
  39. 䒷׏䓸׏ג刿倜 kk@realm.io import UIKit import Accounts import Social import RealmSwift

    class TimelineViewController: UITableViewController { var timeline: Results<Tweet>? var notificationToken: NotificationToken? var account: ACAccount? override func viewDidLoad() { super.viewDidLoad() let accountStore = ACAccountStore() let accountType = accountStore.accountTypeWithAccountTypeIdentifier(ACAccountTypeIdentifierTwitter) accountStore.requestAccessToAccountsWithType(accountType, options: nil) { (granted, error) -> Void in if granted { let accounts = accountStore.accountsWithAccountType(accountType) if let account = accounts.first as? ACAccount { self.account = account self.getHomeTimeline() } else { self.showAlert("No Twitter account") } } else { self.showAlert("No account access") } } tableView.registerNib(UINib(nibName: "TimelineCell", bundle: nil), forCellReuseIdentifier: "timelineCell") tableView.rowHeight = 90 tableView.estimatedRowHeight = 90 let realm = try! Realm() timeline = realm.objects(Tweet).sorted("createdAt", ascending: false) notificationToken = timeline?.addNotificationBlock { [weak self] (change) in switch change { case .Initial(_): self?.tableView.reloadData() case .Update(_, deletions: _, insertions: _, modifications: _): self?.tableView.reloadData() case .Error(_): return } } refreshControl?.addTarget(self, action: #selector(TimelineViewController.refresh(_:)), forControlEvents: .ValueChanged) } func refresh(sender: UIRefreshControl) { if let _ = self.account { getHomeTimeline() } } func getHomeTimeline() { let requestURL = NSURL(string: "https://api.twitter.com/1/statuses/home_timeline.json") let request = SLRequest(forServiceType: SLServiceTypeTwitter, requestMethod: .GET, URL: requestURL, parameters: nil) request.account = account request.performRequestWithHandler { (data, response, error) -> Void in if let error = error { self.showAlert(error.localizedDescription) return } do { let results = try NSJSONSerialization.JSONObjectWithData(data, options: []) if let results = results as? NSDictionary { let errors = results["errors"] as! [[String: AnyObject]] let message = errors.last!["message"] as! String self.showAlert(message) return } let timeline = results as! [[String: AnyObject]] let realm = try! Realm() try! realm.write { timeline.forEach { (tweetDictionary) -> () in let tweet = Tweet(tweetDictionary: tweetDictionary) realm.add(tweet) } } } catch let error as NSError { self.showAlert(error.localizedDescription) } dispatch_async(dispatch_get_main_queue()) { self.refreshControl?.endRefreshing() } } } func showAlert(message: String) { dispatch_async(dispatch_get_main_queue()) { let alertController = UIAlertController(title: "Error", message: message, preferredStyle: .Alert) alertController.addAction(UIAlertAction(title: "OK", style: .Default, handler: nil)) self.presentViewController(alertController, animated: true, completion: nil) } } override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return timeline?.count ?? 0 } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("timelineCell", forIndexPath: indexPath) as! TimelineCell let tweet = timeline![indexPath.row] cell.nameLabel.text = tweet.name cell.tweetTextView.text = tweet.text NSURLSession.sharedSession().dataTaskWithRequest(NSURLRequest(URL: NSURL(string: tweet.iconURL)!)) { (data, response, error) -> Void in if let _ = error { return } dispatch_async(dispatch_get_main_queue()) { let image = UIImage(data: data!)! cell.iconView.image = image } }.resume() return cell } override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return UITableViewAutomaticDimension } }
  40. فٓ؎ؤؗ٦ד ꅾ醱׾《׶ꤐֻ kk@realm.io

  41. Bفٓ؎ؤؗ٦ kk@realm.io class Tweet: Object { dynamic var name =

    "" dynamic var text = "" dynamic var iconURL = "" dynamic var id = "" dynamic var createdAt = NSDate() ... override class func primaryKey() -> String? { return "id" } }
  42. Cفٓ؎ؤؗ٦ kk@realm.io let timeline = results as! [[String: AnyObject]] let

    realm = try! Realm() try! realm.write { timeline.forEach { (tweetDictionary) -> () in let tweet = Tweet(tweetDictionary: tweetDictionary) realm.add(tweet, update: true) } }
  43. 鼅䫛׃׋5XFFU׾ -JLFדֹ׷״ֲחׅ׷ kk@realm.io

  44. kk@realm.io

  45. -JLFׅ׷ kk@realm.io class Tweet: Object { ... dynamic var favorited

    = false convenience init(tweetDictionary: [String: AnyObject]) { ... favorited = tweetDictionary["favorited"] as! Bool } }
  46. -JLFׅ׷ kk@realm.io func postFavorite(id: String) { let realm = try!

    Realm() guard let tweet = realm.objectForPrimaryKey(Tweet.self, key: id) else { return } let requestURL: NSURL if tweet.favorited { requestURL = NSURL(string: "https://api.twitter.com/1.1/favorites/destroy.json")! } else { requestURL = NSURL(string: "https://api.twitter.com/1.1/favorites/create.json")! } let request = SLRequest(forServiceType: SLServiceTypeTwitter, requestMethod: .POST, URL: requestURL, parameters: ["id": request.account = account request.performRequestWithHandler { (data, response, error) -> Void in if let error = error { self.showAlert(error.localizedDescription) return } let realm = try! Realm() if let tweet = realm.objectForPrimaryKey(Tweet.self, key: id) { try! realm.write { tweet.favorited = !tweet.favorited } } } }
  47. -JLFׅ׷ kk@realm.io override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    let tweet = timeline![indexPath.row] postFavorite(tweet.id) tableView.deselectRowAtIndexPath(indexPath, animated: true) }
  48. -JLFׅ׷ kk@realm.io import UIKit import RealmSwift class FavoritesViewController: UITableViewController {

    var likes: Results<Tweet>? var notificationToken: NotificationToken? override func viewDidLoad() { super.viewDidLoad() tableView.registerNib(UINib(nibName: "TimelineCell", bundle: nil), forCellReuseIdentifier: "timelineCell") tableView.rowHeight = 90 tableView.estimatedRowHeight = 90 let realm = try! Realm() likes = realm.objects(Tweet).filter("favorited = %@", true).sorted("createdAt", ascending: false) notificationToken = likes?.addNotificationBlock { [weak self] (change) in switch change { case .Initial(_): self?.tableView.reloadData() case .Update(_, deletions: _, insertions: _, modifications: _): self?.tableView.reloadData() case .Error(_): return } } } // MARK: - Table view data source override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return 1 } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return likes?.count ?? 0 } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("timelineCell", forIndexPath: indexPath) as! TimelineCell let tweet = likes![indexPath.row] cell.nameLabel.text = tweet.name cell.tweetTextView.text = tweet.text NSURLSession.sharedSession().dataTaskWithRequest(NSURLRequest(URL: NSURL(string: tweet.iconURL)!)) { (data, response, error) -> Void in if let _ = error { return } dispatch_async(dispatch_get_main_queue()) { let image = UIImage(data: data!)! cell.iconView.image = image } }.resume() return cell } override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat { return UITableViewAutomaticDimension } }
  49. Where to find us • ! Realm Japan User Group:

    facebook.com/groups/realmjp • ! Twitter: twitter.com/realmJapan • GitHub: github.com/realm • ! StackOverflow: ja.stackoverflow.com/questions/tagged/realm • ! Email: help@realm.io • ! Slack: slack.realm.io/ kk@realm.io
  50. Realm Japan User Group Facebook kk@realm.io

  51. Support Chat Slack kk@realm.io

  52. Ξϯέʔτ bit.ly/RealmJP_Kansai kk@realm.io

  53. Questions? Katsuma Kishikawa kk@realm.io www.realm.io/jp @k_katsumi