Slide 1

Slide 1 text

Realm meetup #18 kk@realm.io

Slide 2

Slide 2 text

#realm_jp kk@realm.io

Slide 3

Slide 3 text

Katsumi Kishikawa Realm Inc. kk@realm.io

Slide 4

Slide 4 text

Recent Updates kk@realm.io

Slide 5

Slide 5 text

Recent Updates • Realm Objective-C/Swift 1.0.2 • Realm Java 1.1.1 (was 1.1.0) • Realm React Native 0.14.0 • Realm Xamarin 0.77.2 (was 0.76.0) kk@realm.io

Slide 6

Slide 6 text

Realm Objective-C/Swift 1.0.2 kk@realm.io

Slide 7

Slide 7 text

Realm Objective-C/Swift 1.0.2 • ϓϩύςΟ͕ଘࡏ͠ͳ͍ΫϥεΛอଘ͠Α͏ͱ͢Δͱྫ֎ʹ • write(_:)ϝιουͷϒϩοΫ಺ͰthrowͰ͖ΔΑ͏ʹ • όΠφϦαΠζ͕গ͠ݮগ • addNotificationBlock(_:, change:)Ͱॳճͷݺͼग़͠͸ඞ ͣ.Initial͕ݺ͹ΕΔΑ͏ʹ • ٯํ޲ͷؔ࿈͕มߋʹͳΔ৔߹ʹ௨஌͕ݺ͹Εͳ͍໰୊Λमਖ਼ jp@realm.io kk@realm.io

Slide 8

Slide 8 text

Already compatible with Swift 3 & Xcode 8 https://github.com/realm/realm-cocoa/issues/3796 kk@realm.io

Slide 9

Slide 9 text

Installing RealmSwift for Xcode 8 beta5 w/ Carthage kk@realm.io github "realm/realm-cocoa" "master"

Slide 10

Slide 10 text

Installing RealmSwift for Xcode 8 beta5 w/ Carthage kk@realm.io $ echo SWIFT_VERSION=\"3.0\">swift3.xcconfig $ XCODE_XCCONFIG_FILE=`pwd`/swift3.xcconfig \ carthage update --no-use-binaries

Slide 11

Slide 11 text

Installing RealmSwift for Xcode 8 beta5 w/ CocoaPods kk@realm.io platform :ios, '8.0' target '...' do use_frameworks! pod 'Realm', git: 'https://github.com/realm/realm-cocoa.git', branch: 'master', submodules: true pod 'RealmSwift', git: 'https://github.com/realm/realm-cocoa.git', branch: 'master', submodules: true post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '3.0' end end end end

Slide 12

Slide 12 text

Installing RealmSwift for Xcode 8 beta5 w/ CocoaPods kk@realm.io platform :ios, '8.0' target '...' do use_frameworks! pod 'Realm', git: '...', branch: 'master', submodules: true pod 'RealmSwift', git: '...', branch: 'master', submodules: true post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '3.0' end end end end

Slide 13

Slide 13 text

Installing RealmSwift for Xcode 8 beta5 w/ CocoaPods kk@realm.io platform :ios, '8.0' target '...' do use_frameworks! pod 'Realm', git: '...', branch: 'master', submodules: true pod 'RealmSwift', git: '...', branch: 'master', submodules: true post_install do |installer| installer.pods_project.targets.each do |target| target.build_configurations.each do |config| config.build_settings['SWIFT_VERSION'] = '3.0' end end end end

Slide 14

Slide 14 text

Realm Xamarin 0.77.2 (was 0.76.0) kk@realm.io

Slide 15

Slide 15 text

Realm Xamarin 0.77.2 • εΩʔϚ৘ใΛࢀর͢ΔAPIͷ௥Ճ • Dynamic APIͷ௥Ճ • realm.CreateObject("ClassName"); • realm.All("ClassName") • RealmList => IList kk@realm.io

Slide 16

Slide 16 text

Best Practice & Tips kk@realm.io

Slide 17

Slide 17 text

Multi thread kk@realm.io

Slide 18

Slide 18 text

Multi thread kk@realm.io func updateUnread(id: String) { let realm = try! Realm() guard let tweet = realm.objectForPrimaryKey(Article.self, key: id) else { return } request.performRequestWithHandler { (data, response, error) in if let error = error { return } ... try! realm.write { tweet.unread = false } } }

Slide 19

Slide 19 text

Multi thread kk@realm.io func updateUnread(id: String) { let realm = try! Realm() guard let tweet = realm.objectForPrimaryKey(Article.self, key: id) else { return } request.performRequestWithHandler { (data, response, error) in if let error = error { return } ... try! realm.write { tweet.unread = false } } } !

Slide 20

Slide 20 text

Basic solution kk@realm.io func updateUnread(id: String) { let realm = try! Realm() guard let tweet = realm.objectForPrimaryKey(Article.self, key: id) else { return } request.performRequestWithHandler { (data, response, error) -> Void in if let error = error { return } let realm = try! Realm() if let tweet = realm.objectForPrimaryKey(Tweet.self, key: id) { try! realm.write { tweet.favorited = !tweet.favorited } } } }

Slide 21

Slide 21 text

Basic solution kk@realm.io func updateUnread(id: String) { let realm = try! Realm() guard let tweet = realm.objectForPrimaryKey(Article.self, key: id) else { return } request.performRequestWithHandler { (data, response, error) -> Void in if let error = error { return } let realm = try! Realm() if let tweet = realm.objectForPrimaryKey(Tweet.self, key: id) { try! realm.write { tweet.favorited = !tweet.favorited } } } }

Slide 22

Slide 22 text

Best practice kk@realm.io var timeline: Results? var notificationToken: NotificationToken? override func viewDidLoad() { super.viewDidLoad() ... let realm = try! Realm() timeline = realm.objects(Article.self) .sorted("creationDate", ascending: false) notificationToken = timeline?.addNotificationBlock { [weak self] (results, error) in if let _ = error { return } self?.tableView.reloadData() } } override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return timeline?.count ?? 0 } func getTimeline() { ... request.performRequestWithHandler { (data, response, error) -> Void in if let error = error { self.showAlert(error.localizedDescription) return } let articles = try NSJSONSerialization.JSONObjectWithData(data, options: []) let realm = try! Realm() try! realm.write { articles.forEach { (article) -> () in ... realm.add(article, update: true) } } } }

Slide 23

Slide 23 text

Best practice kk@realm.io var timeline: Results? var notificationToken: NotificationToken? override func viewDidLoad() { super.viewDidLoad() ... let realm = try! Realm() timeline = realm.objects(Article.self) .sorted("creationDate", ascending: false) notificationToken = timeline?.addNotificationBlock { [weak self] (results, error) in if let _ = error { return } self?.tableView.reloadData() } }

Slide 24

Slide 24 text

Best practice kk@realm.io func getTimeline() { ... request.performRequestWithHandler { (data, response, error) -> Void in if let error = error { self.showAlert(error.localizedDescription) return } let articles = try NSJSONSerialization.JSONObjectWithData(data, options: []) let realm = try! Realm() try! realm.write { articles.forEach { (article) -> () in ... realm.add(article, update: true) } } } }

Slide 25

Slide 25 text

Best practice kk@realm.io func getTimeline() { ... request.performRequestWithHandler { (data, response, error) -> Void in if let error = error { self.showAlert(error.localizedDescription) return } let articles = try NSJSONSerialization.JSONObjectWithData(data, options: []) let realm = try! Realm() try! realm.write { articles.forEach { (article) -> () in ... realm.add(article, update: true) } } } } فٓ؎ؤؗ٦׾ⵃ欽׃ג 鷄⸇،حفر٦ز 傀㶷ך3FTVMUTכ荈⹛涸ח 剑倜ךⰻ㺁ח刿倜ׁ׸׷

Slide 26

Slide 26 text

Migration kk@realm.io

Slide 27

Slide 27 text

Migration Tips kk@realm.io let config = Realm.Configuration(schemaVersion: 1, migrationBlock: { (migration, oldSchemaVersion) in migration.enumerate("") { (oldObject, newObject) in ... } }) Realm.Configuration.defaultConfiguration = config let realm = try! Realm()

Slide 28

Slide 28 text

Migration Tips kk@realm.io let config = Realm.Configuration(schemaVersion: 1, migrationBlock: { (migration, oldSchemaVersion) in migration.enumerate("") { (oldObject, newObject) in ... } }) Realm.Configuration.defaultConfiguration = config let realm = try! Realm()

Slide 29

Slide 29 text

Migration Tips kk@realm.io let config = Realm.Configuration(schemaVersion: 1) Realm.Configuration.defaultConfiguration = config let realm = try! Realm()

Slide 30

Slide 30 text

Migration Tips kk@realm.io class User: Object { dynamic var id = 0 dynamic var name = "" } class User: Object { dynamic var id = 0 dynamic var name = "" dynamic var age 0 }

Slide 31

Slide 31 text

Migration Tips kk@realm.io let config = Realm.Configuration(schemaVersion: 1) Realm.Configuration.defaultConfiguration = config let realm = try! Realm() "

Slide 32

Slide 32 text

Migration Tips kk@realm.io let config = Realm.Configuration(schemaVersion: 1, migrationBlock: { (migration, oldSchemaVersion) in migration.enumerate(User.className()) { (oldObject, newObject) in newObject![“age"] = 18 } }) Realm.Configuration.defaultConfiguration = config let realm = try! Realm() "

Slide 33

Slide 33 text

Migration Tips kk@realm.io class User: Object { dynamic var id = 0 dynamic var firstname = "" dynamic var lastname = "" } class User: Object { dynamic var id = 0 dynamic var fullname = "" }

Slide 34

Slide 34 text

Migration Tips kk@realm.io let config = Realm.Configuration(schemaVersion: 1, migrationBlock: { (migration, oldSchemaVersion) in migration.enumerate(User.className()) { (oldObject, newObject) in let firstname = oldObject!["firstname"] as! String let lastname = oldObject!["lastname"] as! String newObject!["fullname"] = firstname + lastname } }) Realm.Configuration.defaultConfiguration = config let realm = try! Realm() "

Slide 35

Slide 35 text

Reorder table view kk@realm.io

Slide 36

Slide 36 text

Basic solution kk@realm.io class Article: Object { dynamic var name = "" ... dynamic var order = 0 // ฒ΂ସ͑ͷͨΊͷΧϥϜ͕ඞཁ }

Slide 37

Slide 37 text

Basic solution kk@realm.io override func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) { try! realm.write { let sourceObject = objects[sourceIndexPath.row] let destinationObject = objects[destinationIndexPath.row] let destinationObjectOrder = destinationObject.order if sourceIndexPath.row < destinationIndexPath.row { // ্͔ΒԼʹҠಈͨ͠৔߹ɺؒͷ߲໨Λ্ʹγϑτ for index in sourceIndexPath.row...destinationIndexPath.row { let object = objects[index] object.order -= 1 } } else { // Լ͔Β্ʹҠಈͨ͠৔߹ɺؒͷ߲໨ΛԼʹγϑτ for index in (destinationIndexPath.row..

Slide 38

Slide 38 text

Best Practice: List is ordered kk@realm.io class ArticlesWrapper: Object { let articles = List }

Slide 39

Slide 39 text

Best Practice: List is ordered kk@realm.io override func tableView(tableView: UITableView, moveRowAtIndexPath sourceIndexPath: NSIndexPath, toIndexPath destinationIndexPath: NSIndexPath) { try! realm.write { let sourceObject = objects[sourceIndexPath.row] objects.removeAtIndex(sourceIndexPath.row) objects.insert(sourceObject, atIndex: destinationIndexPath.row) } }

Slide 40

Slide 40 text

Table view sections kk@realm.io

Slide 41

Slide 41 text

kk@realm.io

Slide 42

Slide 42 text

Best Practice: List is ordered kk@realm.io class Task: Object { dynamic var name = "" dynamic var notes = "" dynamic var createdAt = NSDate() dynamic var plannedAt = NSDate() dynamic var isCompleted = false }

Slide 43

Slide 43 text

Basic solution kk@realm.io class TableViewController: UITableViewController { ... var objectsBySection = [Results]() override func viewDidLoad() { super.viewDidLoad() ... for section in sectionTitles { let unsortedObjects = realm.objects(Task.self) let sortedObjects = unsortedObjects.sorted("date", ascending: true) objectsBySection.append(sortedObjects) } } override func numberOfSectionsInTableView(tableView: UITableView) -> Int { return sectionTitles.count } override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? { return sectionTitles[section] } override func tableView(tableView: UITableView?, numberOfRowsInSection section: Int) -> Int { return Int(objectsBySection[section].count) }

Slide 44

Slide 44 text

Best Practice: Use relationships kk@realm.io class TaskWrapper: Object { dynamic var date: String = "" // DD MM, YYYY dynamic var tasks = List() override class func primaryKey() -> String { return "date" } }

Slide 45

Slide 45 text

Best Practice: Use relationships kk@realm.io let dateString = dateFormatter.stringFromDate(task.createdAt) var dueDate = realm.objectForPrimaryKey(DueDate.self, key: dateString) if dueDate == nil { dueDate = DueDate() dueDate.date = dateString try! realm.write { realm.add(dueDate, update: true) } } dueDate.tasks.append(task)

Slide 46

Slide 46 text

Best Practice: Use relationships kk@realm.io override func numberOfSectionsInTableView(tableView: UITableView) -> Int { let realm = try! Realm() let sections = realm.objects(TaskWrapper) return sections.count }

Slide 47

Slide 47 text

1:1 inverse relationship kk@realm.io

Slide 48

Slide 48 text

1:1 inverse relationship kk@realm.io class Parent: Object { let children = List() } class Child: Object { let parents = LinkingObjects(fromType: Parent.self, property: "children") }

Slide 49

Slide 49 text

1:1 inverse relationship kk@realm.io class Child: Object { private let parents = LinkingObjects(...) var parent: Parent? { return parents.first } }

Slide 50

Slide 50 text

Mantle with Realm kk@realm.io

Slide 51

Slide 51 text

Mantle with Realm kk@realm.io MTLModel protocol The new protocol represents the basic behaviors expected from any model object, and can be used instead of the MTLModel class when inheritance is impossible, or to create more generic APIs. For example, conformance can be added to the objects from other persistence frameworks in order to use those objects in conjunction with Mantle’s adapters. Accordingly, MTLJSONAdapter has been updated to only depend on conformance, and no longer requires a MTLModel subclass in order to serialize or deserialize from JSON.

Slide 52

Slide 52 text

Mantle with Realm kk@realm.io @interface XYUser : RLMObject @property NSString *name; @property NSDate *createdAt; @end @implementation XYUser + (instancetype)modelWithDictionary:(NSDictionary *)dictionary error:(NSError **)error {...} - (instancetype)initWithDictionary:(NSDictionary *)dictionary error:(NSError **)error {...} + (NSSet *)propertyKeys {...} - (void)mergeValueForKey:(NSString *)key fromModel:(id)model {...} - (NSDictionary *)dictionaryValue {...} - (BOOL)validate:(NSError **)error {...} - (id)copyWithZone:(NSZone *)zone {...} + (NSDictionary *)JSONKeyPathsByPropertyKey {...} + (NSValueTransformer *)createdAtJSONTransformer {...} + (NSDateFormatter *)dateFormatter {...} @end

Slide 53

Slide 53 text

Mantle with Realm kk@realm.io @interface XYUser : RLMObject @property NSString *name; @property NSDate *createdAt; @end @implementation XYUser + (instancetype)modelWithDictionary:(NSDictionary *)dictionary error:(NSError **)error {...} - (instancetype)initWithDictionary:(NSDictionary *)dictionary error:(NSError **)error {...} + (NSSet *)propertyKeys {...} - (void)mergeValueForKey:(NSString *)key fromModel:(id)model {...} - (NSDictionary *)dictionaryValue {...} - (BOOL)validate:(NSError **)error {...} - (id)copyWithZone:(NSZone *)zone {...} + (NSDictionary *)JSONKeyPathsByPropertyKey {...} + (NSValueTransformer *)createdAtJSONTransformer {...} + (NSDateFormatter *)dateFormatter {...} @end

Slide 54

Slide 54 text

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/ jp@realm.io kk@realm.io

Slide 55

Slide 55 text

Realm Japan User Group Facebook kk@realm.io

Slide 56

Slide 56 text

Support Chat Slack kk@realm.io

Slide 57

Slide 57 text

Next meetup • 9/29ʢ໦ʣ 19:30~ • Sansanגࣜձࣾ kk@realm.io

Slide 58

Slide 58 text

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

Slide 59

Slide 59 text

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