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

Kishikawa Katsumi

August 09, 2016
Tweet

More Decks by Kishikawa Katsumi

Other Decks in Programming

Transcript

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

    䒷׏䓸׏ג刿倜ָדֹ׷״ֲחׅ׷  鼅䫛׃׋5XFFU׾-JLFדֹ׷״ֲחׅ׷ ˖ 䘔欽箟  5XFFU׾嗚稊דֹ׷״ֲחׅ׷ [email protected]
  2. 然钠ׅ׷ [email protected] 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 } }
  3. ؐؓ٦ي،حف [email protected] import Foundation import RealmSwift class Tweet: Object {

    dynamic var name = "" dynamic var text = "" dynamic var iconURL = "" dynamic var id = "" dynamic var createdAt = NSDate() }
  4. ؐؓ٦ي،حف [email protected] 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) }
  5. ة؎يٓ؎ٝ׾邌爙 [email protected] import Foundation import RealmSwift class Tweet: Object {

    dynamic var name = "" dynamic var text = "" dynamic var iconURL = "" dynamic var id = "" dynamic var createdAt = NSDate() }
  6. ة؎يٓ؎ٝ׾邌爙 [email protected] 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)! } }
  7. ة؎يٓ؎ٝ׾邌爙 [email protected] 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 } }
  8. Bة؎يٓ؎ٝ׾邌爙 [email protected] 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) } } }
  9. Cة؎يٓ؎ٝ׾邌爙 [email protected] 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") } } }
  10. Cة؎يٓ؎ٝ׾邌爙 [email protected] 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 } } }
  11. ة؎يٓ؎ٝ׾邌爙 [email protected] 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 }
  12. ة؎يٓ؎ٝ׾邌爙 [email protected] 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 } }
  13. C䒷׏䓸׏ג刿倜 [email protected] 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")
  14. D䒷׏䓸׏ג刿倜 [email protected] 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() }
  15. 䒷׏䓸׏ג刿倜 [email protected] 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 } }
  16. Bفٓ؎ؤؗ٦ [email protected] 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" } }
  17. Cفٓ؎ؤؗ٦ [email protected] 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) } }
  18. -JLFׅ׷ [email protected] class Tweet: Object { ... dynamic var favorited

    = false convenience init(tweetDictionary: [String: AnyObject]) { ... favorited = tweetDictionary["favorited"] as! Bool } }
  19. -JLFׅ׷ [email protected] 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 } } } }
  20. -JLFׅ׷ [email protected] override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

    let tweet = timeline![indexPath.row] postFavorite(tweet.id) tableView.deselectRowAtIndexPath(indexPath, animated: true) }
  21. -JLFׅ׷ [email protected] 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 } }
  22. 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: [email protected] • ! Slack: slack.realm.io/ [email protected]