Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func...

267
#WWDC17 © 2017 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple. Rachel Goldeen, Cocoa Engineer Vincent Hittson, Cocoa Engineer Cocoa Development Tips Twenty-nine things you may not know about Cocoa Session 236 App Frameworks

Transcript of Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func...

Page 1: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

#WWDC17

© 2017 Apple Inc. All rights reserved. Redistribution or public display not permitted without written permission from Apple.

Rachel Goldeen, Cocoa Engineer Vincent Hittson, Cocoa Engineer

•Cocoa Development Tips •Twenty-nine things you may not know about Cocoa • Session 236

App Frameworks

Page 2: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Internationalization

π

Page 3: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Internationalization Xcode Scheme Options

Page 4: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Internationalization Xcode Scheme Options

Page 5: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Internationalization Xcode Scheme Options

Page 6: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Internationalization Xcode Scheme Options

Page 7: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Internationalization Xcode Scheme Options

Page 8: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Internationalization Xcode Scheme Options

Page 9: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

0

Page 10: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

UserDefaults.standard

Page 11: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

Argument Domain

Application Domain

Global Domain

Registration Domain

Page 12: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

Argument Domain

Application Domain

Global Domain

Registration Domain

Page 13: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

UserDefaults.standard.object(forKey:"showAtLaunch")Argument Domain

Application Domain

Global Domain

Registration Domain

Page 14: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

UserDefaults.standard.object(forKey:"showAtLaunch")

Argument Domain

Application Domain

Global Domain

Registration Domain

Page 15: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

Argument Domain

Application Domain

Global Domain

Registration Domain

Page 16: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

Argument Domain

Application Domain

Global Domain

Registration Domain UserDefaults.standard.register(["showAtLaunch": true])

Page 17: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

Argument Domain

Application Domain

Global Domain

Registration Domain UserDefaults.standard.register(["showAtLaunch": true])

Page 18: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Temporary

User Defaults

Argument Domain

Application Domain

Global Domain

Registration Domain UserDefaults.standard.register(["showAtLaunch": true])

Page 19: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Argument Domain

Application Domain

Registration Domain

User Defaults

Global Domain

Page 20: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Argument Domain

Application Domain

Registration Domain

User Defaults

$ defaults write NSGlobalDomain \ showAtLaunch -bool YES

Global Domain

Page 21: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Argument Domain

Application Domain

Registration Domain

User Defaults

$ defaults write NSGlobalDomain \ showAtLaunch -bool YES

Global Domain

Page 22: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Persistent

Argument Domain

Application Domain

Registration Domain

User Defaults

$ defaults write NSGlobalDomain \ showAtLaunch -bool YES

Global Domain

Page 23: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Argument Domain

Application Domain

Global Domain

Registration Domain

User Defaults

Page 24: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Argument Domain

Application Domain

Global Domain

Registration Domain

User Defaults

UserDefaults.standard.set(true, forKey:"showAtLaunch")

Page 25: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Argument Domain

Application Domain

Global Domain

Registration Domain

User Defaults

UserDefaults.standard.set(true, forKey:"showAtLaunch")

Page 26: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

PersistentArgument Domain

Application Domain

Global Domain

Registration Domain

User Defaults

UserDefaults.standard.set(true, forKey:"showAtLaunch")

Page 27: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Argument Domain

Application Domain

Global Domain

Registration Domain

User Defaults

Page 28: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Argument Domain

Application Domain

Global Domain

Registration Domain

User Defaults

Page 29: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Temporary

Argument Domain

Application Domain

Global Domain

Registration Domain

User Defaults

Page 30: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

Page 31: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

-NSViewLayoutFeedbackLoopDebuggingEnabled YES

Page 32: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

-NSViewLayoutFeedbackLoopDebuggingEnabled YES

-NSApplicationCrashOnExceptions YES

Page 33: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

Key-value observing is supported for UserDefaults.standard • Add an observer with the user defaults key as the keyPath • Supports cross-process observation

Page 34: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class MyUserDefaultsObserver: NSObject { private var ctx = 0 func startObserving() { UserDefaults.standard.addObserver(self, forKeyPath: "showAtLaunch", options: [], context: &ctx) } func stopObserving { UserDefaults.standard.removeObserver(self, forKeyPath: "showAtLaunch", context: &ctx) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, …, context: …) { if context == &ctx { preferencesChanged() } else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: …) } } }

Page 35: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class MyUserDefaultsObserver: NSObject { private var ctx = 0 func startObserving() { UserDefaults.standard.addObserver(self, forKeyPath: "showAtLaunch", options: [], context: &ctx) } func stopObserving { UserDefaults.standard.removeObserver(self, forKeyPath: "showAtLaunch", context: &ctx) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, …, context: …) { if context == &ctx { preferencesChanged() } else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: …) } } }

Page 36: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class MyUserDefaultsObserver: NSObject { private var ctx = 0 func startObserving() { UserDefaults.standard.addObserver(self, forKeyPath: "showAtLaunch", options: [], context: &ctx) } func stopObserving { UserDefaults.standard.removeObserver(self, forKeyPath: "showAtLaunch", context: &ctx) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, …, context: …) { if context == &ctx { preferencesChanged() } else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: …) } } }

Page 37: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class MyUserDefaultsObserver: NSObject { private var ctx = 0 func startObserving() { UserDefaults.standard.addObserver(self, forKeyPath: "showAtLaunch", options: [], context: &ctx) } func stopObserving { UserDefaults.standard.removeObserver(self, forKeyPath: "showAtLaunch", context: &ctx) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, …, context: …) { if context == &ctx { preferencesChanged() } else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: …) } } }

Page 38: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class MyUserDefaultsObserver: NSObject { private var ctx = 0 func startObserving() { UserDefaults.standard.addObserver(self, forKeyPath: "showAtLaunch", options: [], context: &ctx) } func stopObserving { UserDefaults.standard.removeObserver(self, forKeyPath: "showAtLaunch", context: &ctx) } override func observeValue(forKeyPath keyPath: String?, of object: Any?, …, context: …) { if context == &ctx { preferencesChanged() } else { super.observeValue(forKeyPath: keyPath, of: object, change: change, context: …) } } }

Page 39: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

Page 40: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

UserDefaults.standard My Application

Page 41: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

UserDefaults.standard.set(…)

User Defaults

UserDefaults.standard My Application

Page 42: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

UserDefaults.standard My Application

Page 43: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

observeValue(forKeyPath:…)

User Defaults

UserDefaults.standard My Application

Page 44: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

UserDefaults.standard My Application

Page 45: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

UserDefaults.standard My ApplicationOther Process

Page 46: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

set(…)

User Defaults

UserDefaults.standard My ApplicationOther Process

Page 47: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

UserDefaults.standard My ApplicationOther Process

Page 48: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

observeValue(…)

User Defaults

UserDefaults.standard My ApplicationOther Process

Page 49: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

User Defaults

UserDefaults.standard My ApplicationOther Process

Page 50: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension UserDefaults { @objc dynamic var showAtLaunch: Bool { return self.value(forKey:"showAtLaunch") as? Bool ?? false }} let observation = UserDefaults.standard.observe(\.showAtLaunch) { observed, change in preferencesChanged()

}

NEW

Page 51: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension UserDefaults { @objc dynamic var showAtLaunch: Bool { return self.value(forKey:"showAtLaunch") as? Bool ?? false }} let observation = UserDefaults.standard.observe(\.showAtLaunch) { observed, change in preferencesChanged()

}

NEW

Page 52: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension UserDefaults { @objc dynamic var showAtLaunch: Bool { return self.value(forKey:"showAtLaunch") as? Bool ?? false }} let observation = UserDefaults.standard.observe(\.showAtLaunch) { observed, change in preferencesChanged()

}

NEW

Page 53: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension UserDefaults { @objc dynamic var showAtLaunch: Bool { return self.value(forKey:"showAtLaunch") as? Bool ?? false }} let observation = UserDefaults.standard.observe(\.showAtLaunch) { observed, change in preferencesChanged()

}

NEW

Page 54: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension UserDefaults { @objc dynamic var showAtLaunch: Bool { return self.value(forKey:"showAtLaunch") as? Bool ?? false }} let observation = UserDefaults.standard.observe(\.showAtLaunch) { observed, change in preferencesChanged()

}

NEW

Page 55: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

QmFzZSA2NAo=

64

Page 56: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Base 64

64

Page 57: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let data64 = "//lsYAFgAADQQAf/+WxgD6AAAPSbwD4pTJg0QK0CZA2QK0CZCxkIEyAwRLb/j/uqvrPd68f+T8v+j/5 d+3v89/P/p/pf/rn+PA+kH0HY8NoBsAMCKIu4JCcHNa4XAPztvtvoaHatuD3eKQzN1NdNZzsb9+8P5bDV8v/ZuNVFSCg1 1bGixouwcP/5bGApQAABANGAJFAghgdjEIFsoCcNjAId/9vfvv8LfvxxOs64Bse/v7j4b+Kff7tNA8ywhZqZoSVUqr/LG aheO9OT5w8u5R01m3kv0T8b7HvfCN17LwzsiPfg/tdl64//N2Rc9mAABorJxTzCoPtzL6o8rCMYow0cdQeLDjb5Dj3tog Ut1rupUyJr6vfG8fjq9mm3B3RhFuDIQp5CrSIY7AkMPnCGnypF9Enh7PCrv1KRogFGFLAALR63FtFhIKITpWiFXLk4mmJ GyhGPgSVCYRoDJKRwkAmxOQGyqPnf+BnQhFiieDxZKPVIazbEZPEifeOwkKHl0h8DvhGQ9CIJ+X/cRP256DJ+A9oQqbIh u9aQyEAnLyZPY8TJ846gT6Xygnr5RCBPIrWTvZYnpdQTz2KtaaQl2yFaBmHv8mddTm0RjgUs0AAA4P/5bGAQQAAA9hGAS EA8EBCBsQEoLhAJ2//tet7/6x8gO0sSGae3rM3VUoc5RwmpFzXBc5yL2UUFRSJKWVldlXfNV4qhPCBEkvBDGoUIiCAaEm Dvyms7n+/569VIjJvJcfPgAAARRRIBIkvWKsRQrFSxa0P2/K6fre78DwfPWtooAA7/+WxgCsAAAPQRgGhgMYYCCbCoQI4 RCAWw//ty+XIl4yBxb16igW28pmWXEywjHf/riV3BvCOEAAEzTI0d5phGYo2+v+HzxgAAAKvV+L6nwtLw4soBwP/5bGAP oAAA9BGAZCAJJgQhAZCAQhoIhAjiAJoFMzl8P2c62HfeE/xm+IPeH4MPcZMyfeF/M77l8ZnfeHIZ33JQnCW7J6muscXBt qrbRpag2fQf4Nn0H+BHLYJ1nVHVOPdW253mWvMfBgAC11njl1W3k6vofG8vm5SgAAHA"

let soundData = Data(base64Encoded: data64)! let sound = NSSound(data: soundData)! sound.play()

Page 58: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let data64 = "//lsYAFgAADQQAf/+WxgD6AAAPSbwD4pTJg0QK0CZA2QK0CZCxkIEyAwRLb/j/uqvrPd68f+T8v+j/5 d+3v89/P/p/pf/rn+PA+kH0HY8NoBsAMCKIu4JCcHNa4XAPztvtvoaHatuD3eKQzN1NdNZzsb9+8P5bDV8v/ZuNVFSCg1 1bGixouwcP/5bGApQAABANGAJFAghgdjEIFsoCcNjAId/9vfvv8LfvxxOs64Bse/v7j4b+Kff7tNA8ywhZqZoSVUqr/LG aheO9OT5w8u5R01m3kv0T8b7HvfCN17LwzsiPfg/tdl64//N2Rc9mAABorJxTzCoPtzL6o8rCMYow0cdQeLDjb5Dj3tog Ut1rupUyJr6vfG8fjq9mm3B3RhFuDIQp5CrSIY7AkMPnCGnypF9Enh7PCrv1KRogFGFLAALR63FtFhIKITpWiFXLk4mmJ GyhGPgSVCYRoDJKRwkAmxOQGyqPnf+BnQhFiieDxZKPVIazbEZPEifeOwkKHl0h8DvhGQ9CIJ+X/cRP256DJ+A9oQqbIh u9aQyEAnLyZPY8TJ846gT6Xygnr5RCBPIrWTvZYnpdQTz2KtaaQl2yFaBmHv8mddTm0RjgUs0AAA4P/5bGAQQAAA9hGAS EA8EBCBsQEoLhAJ2//tet7/6x8gO0sSGae3rM3VUoc5RwmpFzXBc5yL2UUFRSJKWVldlXfNV4qhPCBEkvBDGoUIiCAaEm Dvyms7n+/569VIjJvJcfPgAAARRRIBIkvWKsRQrFSxa0P2/K6fre78DwfPWtooAA7/+WxgCsAAAPQRgGhgMYYCCbCoQI4 RCAWw//ty+XIl4yBxb16igW28pmWXEywjHf/riV3BvCOEAAEzTI0d5phGYo2+v+HzxgAAAKvV+L6nwtLw4soBwP/5bGAP oAAA9BGAZCAJJgQhAZCAQhoIhAjiAJoFMzl8P2c62HfeE/xm+IPeH4MPcZMyfeF/M77l8ZnfeHIZ33JQnCW7J6muscXBt qrbRpag2fQf4Nn0H+BHLYJ1nVHVOPdW253mWvMfBgAC11njl1W3k6vofG8vm5SgAAHA"

let soundData = Data(base64Encoded: data64)! let sound = NSSound(data: soundData)! sound.play()

Page 59: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let data64 = "//lsYAFgAADQQAf/+WxgD6AAAPSbwD4pTJg0QK0CZA2QK0CZCxkIEyAwRLb/j/uqvrPd68f+T8v+j/5 d+3v89/P/p/pf/rn+PA+kH0HY8NoBsAMCKIu4JCcHNa4XAPztvtvoaHatuD3eKQzN1NdNZzsb9+8P5bDV8v/ZuNVFSCg1 1bGixouwcP/5bGApQAABANGAJFAghgdjEIFsoCcNjAId/9vfvv8LfvxxOs64Bse/v7j4b+Kff7tNA8ywhZqZoSVUqr/LG aheO9OT5w8u5R01m3kv0T8b7HvfCN17LwzsiPfg/tdl64//N2Rc9mAABorJxTzCoPtzL6o8rCMYow0cdQeLDjb5Dj3tog Ut1rupUyJr6vfG8fjq9mm3B3RhFuDIQp5CrSIY7AkMPnCGnypF9Enh7PCrv1KRogFGFLAALR63FtFhIKITpWiFXLk4mmJ GyhGPgSVCYRoDJKRwkAmxOQGyqPnf+BnQhFiieDxZKPVIazbEZPEifeOwkKHl0h8DvhGQ9CIJ+X/cRP256DJ+A9oQqbIh u9aQyEAnLyZPY8TJ846gT6Xygnr5RCBPIrWTvZYnpdQTz2KtaaQl2yFaBmHv8mddTm0RjgUs0AAA4P/5bGAQQAAA9hGAS EA8EBCBsQEoLhAJ2//tet7/6x8gO0sSGae3rM3VUoc5RwmpFzXBc5yL2UUFRSJKWVldlXfNV4qhPCBEkvBDGoUIiCAaEm Dvyms7n+/569VIjJvJcfPgAAARRRIBIkvWKsRQrFSxa0P2/K6fre78DwfPWtooAA7/+WxgCsAAAPQRgGhgMYYCCbCoQI4 RCAWw//ty+XIl4yBxb16igW28pmWXEywjHf/riV3BvCOEAAEzTI0d5phGYo2+v+HzxgAAAKvV+L6nwtLw4soBwP/5bGAP oAAA9BGAZCAJJgQhAZCAQhoIhAjiAJoFMzl8P2c62HfeE/xm+IPeH4MPcZMyfeF/M77l8ZnfeHIZ33JQnCW7J6muscXBt qrbRpag2fQf4Nn0H+BHLYJ1nVHVOPdW253mWvMfBgAC11njl1W3k6vofG8vm5SgAAHA"

let soundData = Data(base64Encoded: data64)! let sound = NSSound(data: soundData)! sound.play()

Page 60: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let data64 = "//lsYAFgAADQQAf/+WxgD6AAAPSbwD4pTJg0QK0CZA2QK0CZCxkIEyAwRLb/j/uqvrPd68f+T8v+j/5 d+3v89/P/p/pf/rn+PA+kH0HY8NoBsAMCKIu4JCcHNa4XAPztvtvoaHatuD3eKQzN1NdNZzsb9+8P5bDV8v/ZuNVFSCg1 1bGixouwcP/5bGApQAABANGAJFAghgdjEIFsoCcNjAId/9vfvv8LfvxxOs64Bse/v7j4b+Kff7tNA8ywhZqZoSVUqr/LG aheO9OT5w8u5R01m3kv0T8b7HvfCN17LwzsiPfg/tdl64//N2Rc9mAABorJxTzCoPtzL6o8rCMYow0cdQeLDjb5Dj3tog Ut1rupUyJr6vfG8fjq9mm3B3RhFuDIQp5CrSIY7AkMPnCGnypF9Enh7PCrv1KRogFGFLAALR63FtFhIKITpWiFXLk4mmJ GyhGPgSVCYRoDJKRwkAmxOQGyqPnf+BnQhFiieDxZKPVIazbEZPEifeOwkKHl0h8DvhGQ9CIJ+X/cRP256DJ+A9oQqbIh u9aQyEAnLyZPY8TJ846gT6Xygnr5RCBPIrWTvZYnpdQTz2KtaaQl2yFaBmHv8mddTm0RjgUs0AAA4P/5bGAQQAAA9hGAS EA8EBCBsQEoLhAJ2//tet7/6x8gO0sSGae3rM3VUoc5RwmpFzXBc5yL2UUFRSJKWVldlXfNV4qhPCBEkvBDGoUIiCAaEm Dvyms7n+/569VIjJvJcfPgAAARRRIBIkvWKsRQrFSxa0P2/K6fre78DwfPWtooAA7/+WxgCsAAAPQRgGhgMYYCCbCoQI4 RCAWw//ty+XIl4yBxb16igW28pmWXEywjHf/riV3BvCOEAAEzTI0d5phGYo2+v+HzxgAAAKvV+L6nwtLw4soBwP/5bGAP oAAA9BGAZCAJJgQhAZCAQhoIhAjiAJoFMzl8P2c62HfeE/xm+IPeH4MPcZMyfeF/M77l8ZnfeHIZ33JQnCW7J6muscXBt qrbRpag2fQf4Nn0H+BHLYJ1nVHVOPdW253mWvMfBgAC11njl1W3k6vofG8vm5SgAAHA"

let soundData = Data(base64Encoded: data64)! let sound = NSSound(data: soundData)! sound.play()

Page 61: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

soundData.base64EncodedString()

"//lsYAFgAADQQAf/+WxgD6AAAPSbwD4pTJg0QK0CZA2QK0CZCxkIEyAwRLb/j/uqvrPd68f+T8v+j/5d+3v89/P/p/pf /rn+PA+kH0HY8NoBsAMCKIu4JCcHNa4XAPztvtvoaHatuD3eKQzN1NdNZzsb9+8P5bDV8v/ZuNVFSCg11bGixouwcP/5b GApQAABANGAJFAghgdjEIFsoCcNjAId/9vfvv8LfvxxOs64Bse/v7j4b+Kff7tNA8ywhZqZoSVUqr/LGaheO9OT5w8u5R 01m3kv0T8b7HvfCN17LwzsiPfg/tdl64//N2Rc9mAABorJxTzCoPtzL6o8rCMYow0cdQeLDjb5Dj3togUt1rupUyJr6vf G8fjq9mm3B3RhFuDIQp5CrSIY7AkMPnCGnypF9Enh7PCrv1KRogFGFLAALR63FtFhIKITpWiFXLk4mmJGyhGPgSVCYRoD JKRwkAmxOQGyqPnf+BnQhFiieDxZKPVIazbEZPEifeOwkKHl0h8DvhGQ9CIJ+X/cRP256DJ+A9oQqbIhu9aQyEAnLyZPY 8TJ846gT6Xygnr5RCBPIrWTvZYnpdQTz2KtaaQl2yFaBmHv8mddTm0RjgUs0AAA4P/5bGAQQAAA9hGASEA8EBCBsQEoLh AJ2//tet7/6x8gO0sSGae3rM3VUoc5RwmpFzXBc5yL2UUFRSJKWVldlXfNV4qhPCBEkvBDGoUIiCAaEmDvyms7n+/569V IjJvJcfPgAAARRRIBIkvWKsRQrFSxa0P2/K6fre78DwfPWtooAA7/+WxgCsAAAPQRgGhgMYYCCbCoQI4RCAWw//ty+XIl 4yBxb16igW28pmWXEywjHf/riV3BvCOEAAEzTI0d5phGYo2+v+HzxgAAAKvV+L6nwtLw4soBwP/5bGAPoAAA9BGAZCAJJ gQhAZCAQhoIhAjiAJoFMzl8P2c62HfeE/xm+IPeH4MPcZMyfeF/M77l8ZnfeHIZ33JQnCW7J6muscXBtqrbRpag2fQf4N n0H+BHLYJ1nVHVOPdW253mWvMfBgAC11njl1W3k6vofG8vm5SgAAHA"

Page 62: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Asset Catalogs

2X

Page 63: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Asset Catalogs

Page 64: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Asset Catalogs Layout direction

Page 65: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Asset Catalogs Layout direction

Page 66: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Asset Catalogs Layout direction

Page 67: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Asset Catalogs Display gamut

v1x

sRGB2x

sRGB

1x Display P3

2x Display P3

Page 68: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Asset Catalogs Colors

NEW

Page 69: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Asset Catalogs Colors

Page 70: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Asset Catalogs Colors

Page 71: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

//Using colors from Asset Catalogs

//You can add your color name to the extensible NSColor.Name enum extension NSColor.Name {

static let accent = NSColor.Name("Accent")

} //Then you can create your color using that name

let accentColor = NSColor(named: .accent)

Page 72: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Unit Tests

1

Page 73: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Unit Tests

Even the most basic test is better than no test

Page 74: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Unit Tests

Page 75: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Unit Tests

Page 76: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

func testExample() { // This is an example of a functional test case. // Use XCTAssert and related functions to verify your tests // produce the correct results. }

Page 77: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

func testCatImage() { let addCatImage = NSImage(named: NSImage.Name("AddCat")) XCTAssertNotNil(addCatImage) }

Page 78: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSBox

27

Page 79: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 80: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let view = MyView()view.backgroundColor = .systemPurple

Page 81: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let view = MyView()view.backgroundColor = .systemPurple

Page 82: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class MyView: NSView { public var backgroundColor = NSColor.clear override func draw(_ dirtyRect: NSRect) { backgroundColor.setFill() bounds.fill() }}

Page 83: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class MyView: NSView { override init(frame: NSRect) { super.init(frame: frame) wantsLayer = true wantsUpdateLayer = true } required init?(coder: NSCoder) { super.init(coder: coder) wantsLayer = true wantsUpdateLayer = true }

public var backgroundColor = NSColor.clear override func updateLayer() { layer?.backgroundColor = backgroundColor.cgColor }}

Page 84: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let box = NSBox() box.boxType = .custom box.borderWidth = 0 box.fillColor = .systemPurple

Page 85: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let box = NSBox() box.boxType = .custom box.borderWidth = 0 box.fillColor = .systemPurple

Page 86: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let box = NSBox() box.boxType = .custom box.borderWidth = 0 box.fillColor = .systemPurple

Page 87: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

open class NSBox : NSView { open var borderWidth: CGFloat open var cornerRadius: CGFloat @NSCopying open var borderColor: NSColor @NSCopying open var fillColor: NSColor

open var contentView: NSView?

}

Page 88: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

open class NSBox : NSView { open var borderWidth: CGFloat open var cornerRadius: CGFloat @NSCopying open var borderColor: NSColor @NSCopying open var fillColor: NSColor

open var contentView: NSView?

}

Page 89: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

open class NSBox : NSView { open var borderWidth: CGFloat open var cornerRadius: CGFloat @NSCopying open var borderColor: NSColor @NSCopying open var fillColor: NSColor

open var contentView: NSView?

}

Page 90: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

open class NSBox : NSView { open var borderWidth: CGFloat open var cornerRadius: CGFloat @NSCopying open var borderColor: NSColor @NSCopying open var fillColor: NSColor

open var contentView: NSView?

}

Page 91: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 92: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let box = NSBox() box.boxType = .separator

Page 93: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let box = NSBox() box.boxType = .separator

Page 94: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let box = NSBox() box.boxType = .separator

Page 95: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Restorable State

8

Page 96: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSResponder { open func encodeRestorableState(with coder: NSCoder) open func restoreState(with coder: NSCoder) open func invalidateRestorableState()}

Page 97: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSResponder { open func encodeRestorableState(with coder: NSCoder) open func restoreState(with coder: NSCoder) open func invalidateRestorableState()}

Page 98: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

var selectedItem: String { didSet { invalidateRestorableState() } } var documentIdentifier: String { didSet { invalidateRestorableState() } } override func encodeRestorableState(with coder: NSCoder) { super.encodeRestorableState(with: coder) coder.encode(documentIdentifier, forKey: "documentIdentifier") coder.encode(selectedItem, forKey: "selectedItem") } override func restoreState(with coder: NSCoder) { super.restoreState(with: coder) if let di = coder.decodeObject(forKey: "documentIdentifier") as? String { documentIdentifier = di } if let si = coder.decodeObject(forKey: "selectedItem") as? String { selectedItem = si } }

Page 99: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

var selectedItem: String { didSet { invalidateRestorableState() } } var documentIdentifier: String { didSet { invalidateRestorableState() } } override func encodeRestorableState(with coder: NSCoder) { super.encodeRestorableState(with: coder) coder.encode(documentIdentifier, forKey: "documentIdentifier") coder.encode(selectedItem, forKey: "selectedItem") } override func restoreState(with coder: NSCoder) { super.restoreState(with: coder) if let di = coder.decodeObject(forKey: "documentIdentifier") as? String { documentIdentifier = di } if let si = coder.decodeObject(forKey: "selectedItem") as? String { selectedItem = si } }

Page 100: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

var selectedItem: String { didSet { invalidateRestorableState() } } var documentIdentifier: String { didSet { invalidateRestorableState() } } override func encodeRestorableState(with coder: NSCoder) { super.encodeRestorableState(with: coder) coder.encode(documentIdentifier, forKey: "documentIdentifier") coder.encode(selectedItem, forKey: "selectedItem") } override func restoreState(with coder: NSCoder) { super.restoreState(with: coder) if let di = coder.decodeObject(forKey: "documentIdentifier") as? String { documentIdentifier = di } if let si = coder.decodeObject(forKey: "selectedItem") as? String { selectedItem = si } }

Page 101: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

var selectedItem: String { didSet { invalidateRestorableState() } } var documentIdentifier: String { didSet { invalidateRestorableState() } } override func encodeRestorableState(with coder: NSCoder) { super.encodeRestorableState(with: coder) coder.encode(documentIdentifier, forKey: "documentIdentifier") coder.encode(selectedItem, forKey: "selectedItem") } override func restoreState(with coder: NSCoder) { super.restoreState(with: coder) if let di = coder.decodeObject(forKey: "documentIdentifier") as? String { documentIdentifier = di } if let si = coder.decodeObject(forKey: "selectedItem") as? String { selectedItem = si } }

Page 102: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

var selectedItem: String { didSet { invalidateRestorableState() } } var documentIdentifier: String { didSet { invalidateRestorableState() } } override func encodeRestorableState(with coder: NSCoder) { super.encodeRestorableState(with: coder) coder.encode(documentIdentifier, forKey: "documentIdentifier") coder.encode(selectedItem, forKey: "selectedItem") } override func restoreState(with coder: NSCoder) { super.restoreState(with: coder) if let di = coder.decodeObject(forKey: "documentIdentifier") as? String { documentIdentifier = di } if let si = coder.decodeObject(forKey: "selectedItem") as? String { selectedItem = si } }

Page 103: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSResponder { open class var restorableStateKeyPaths: [String] { get }}

Page 104: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSResponder { open class var restorableStateKeyPaths: [String] { get }}

Page 105: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

@objc dynamic var selectedItem: String @objc dynamic var documentIdentifier: String

override class var restorableStateKeyPaths: [String] { return super.restorableStateKeyPaths + [ #keyPath(ViewController.documentIdentifier), #keyPath(ViewController.selectedItem)] }

Page 106: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

@objc dynamic var selectedItem: String @objc dynamic var documentIdentifier: String

override class var restorableStateKeyPaths: [String] { return super.restorableStateKeyPaths + [ #keyPath(ViewController.documentIdentifier), #keyPath(ViewController.selectedItem)] }

Page 107: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

@objc dynamic var selectedItem: String @objc dynamic var documentIdentifier: String

override class var restorableStateKeyPaths: [String] { return super.restorableStateKeyPaths + [ #keyPath(ViewController.documentIdentifier), #keyPath(ViewController.selectedItem)] }

Page 108: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

@objc dynamic var selectedItem: String @objc dynamic var documentIdentifier: String

override class var restorableStateKeyPaths: [String] { return super.restorableStateKeyPaths + [ #keyPath(ViewController.documentIdentifier), #keyPath(ViewController.selectedItem)] }

Page 109: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data: NSPersistentContainer

13

Page 110: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

What Is a Core Data Stack?

Page 111: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

What Is a Core Data Stack?

NSManagedObjectModel

Page 112: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

What Is a Core Data Stack?

NSManagedObjectModel

NSPersistentStoreCoordinator

Page 113: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

What Is a Core Data Stack?

NSManagedObjectContext

NSManagedObjectModel

NSPersistentStoreCoordinator

Page 114: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class DataControllerOld: NSObject {

var applicationDocumentsDirectory: URL = {

let urls = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)

return urls[urls.count-1]}()

var managedObjectModel: NSManagedObjectModel = {

let modelURL = Bundle.main.url(forResource: "AppName", withExtension: "momd")!

return NSManagedObjectModel(contentsOf: modelURL)!}()

var persistentStoreCoordinator: NSPersistentStoreCoordinator = {

let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)

let url = self.applicationDocumentsDirectory.appendingPathComponent("AppName.sqlite")

do {

try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)

} catch {

// Replace this with code to handle the error appropriately.

fatalError("Unresolved error \(error), \(error.userInfo)")

}

return coordinator}()

Page 115: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let coordinator = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)

let url = self.applicationDocumentsDirectory.appendingPathComponent("AppName.sqlite")

do {

try coordinator.addPersistentStore(ofType: NSSQLiteStoreType, configurationName: nil, at: url, options: nil)

} catch {

// Replace this with code to handle the error appropriately.

fatalError("Unresolved error \(error), \(error.userInfo)")

}

return coordinator}()

var managedObjectContext: NSManagedObjectContext = {

let coordinator = self.persistentStoreCoordinator

var managedObjectContext = NSManagedObjectContext(concurrencyType: .mainQueueConcurrencyType)

managedObjectContext.persistentStoreCoordinator = coordinator

return managedObjectContext

}()

}

Page 116: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSManagedObjectContext

NSManagedObjectModel

NSPersistentStoreCoordinator

NSPersistentContainer Encapsulates the Stack

Page 117: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSPersistentContainer

NSManagedObjectContext

NSManagedObjectModel

NSPersistentStoreCoordinator

NSPersistentContainer Encapsulates the Stack

Page 118: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class DataControllerNew: NSObject { var persistentContainer: NSPersistentContainer init(completionClosure: @escaping () -> ()) { persistentContainer = NSPersistentContainer(name: "DataModel") persistentContainer.loadPersistentStores() { (description, error) in if let error = error { // Handle the error here, depending on what it is } completionClosure() } } }

Page 119: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class DataControllerNew: NSObject { var persistentContainer: NSPersistentContainer init(completionClosure: @escaping () -> ()) { persistentContainer = NSPersistentContainer(name: "DataModel") persistentContainer.loadPersistentStores() { (description, error) in if let error = error { // Handle the error here, depending on what it is } completionClosure() } } }

Page 120: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data: Arrays

21

Page 121: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 122: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Arrays

Page 123: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 124: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 125: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 126: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Arrays

Page 127: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Arrays

Page 128: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Arrays

Page 129: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Arrays

Page 130: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Arrays

Added overhead for serializing and deserializing the array and its contents

Page 131: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Arrays

Added overhead for serializing and deserializing the array and its contents

Fetch requests are much slower

Page 132: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Relationships

Page 133: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data To many relationships

Page 134: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data To many relationships

Page 135: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data To many relationships

Page 136: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data To many relationships

Page 137: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data: Migration

34

Page 138: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 139: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 140: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 141: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 142: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Migration

Page 143: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Migration

Page 144: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Migration

Page 145: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Lightweight migration automatic with NSPersistentContainer

Core Data Migration

Page 146: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Migration

Lightweight migration automatic with NSPersistentContainer

Otherwise use shouldInferMappingModelAutomatically and NSMigratePersistentStoresAutomaticallyOption

Page 147: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data: Error Handling

55

Page 148: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Core Data Error handling

Pay attention to errors

Most important when adding a persistent store

App won’t work if persistent store can’t be added

Handle these errors even if you ignore all others

Page 149: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class DataControllerNew: NSObject { var persistentContainer: NSPersistentContainer init(completionClosure: @escaping () -> ()) { persistentContainer = NSPersistentContainer(name: "DataModel") persistentContainer.loadPersistentStores() { (description, error) in

// Some common error conditions are: // - not enough storage space // - unable to access store due to permissions issues or // data protection // - trying to add a store created with an older model // without a proper migration strategy

if let error = error { // Handle the error here, depending on what it is } completionClosure() } } }

Page 150: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSError

404

Page 151: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSError

Cocoa APIs return NSErrors that you can present to the user

Page 152: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSResponder {

open func presentError(_: Error) -> Bool }

Page 153: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSResponder {

open func presentError(_: Error) -> Bool }

Page 154: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSResponder {

open func presentError(_: Error) -> Bool }

Page 155: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

throw NSError(domain: NSCocoaErrorDomain, code: NSFileReadCorruptFileError, userInfo: [ NSURLErrorKey: fileURL ])

Page 156: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

throw NSError(domain: NSCocoaErrorDomain, code: NSFileReadCorruptFileError, userInfo: [ NSURLErrorKey: fileURL ])

Page 157: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

public var NSFileNoSuchFileError: Int { get } // Attempt to do a file system operation on a non-existent filepublic var NSFileLockingError: Int { get } // Couldn't get a lock on filepublic var NSFileReadUnknownError: Int { get } // Read error (reason unknown)public var NSFileReadNoPermissionError: Int { get } // Read error (permission problem)public var NSFileReadInvalidFileNameError: Int { get } // Read error (invalid file name)public var NSFileReadCorruptFileError: Int { get } // Read error (file corrupt, bad format, etc) public var NSFileReadNoSuchFileError: Int { get } // Read error (no such file)public var NSFileReadInapplicableStringEncodingError: Int { get } // Read error (string encoding not applicable) also NSStringEncodingErrorKey public var NSFileReadUnsupportedSchemeError: Int { get } // Read error (unsupported URL scheme)public var NSFileReadTooLargeError: Int { get } // Read error (file too large)public var NSFileReadUnknownStringEncodingError: Int { get } // Read error (string encoding of file contents could not be determined)public var NSFileWriteUnknownError: Int { get } // Write error (reason unknown)

Page 158: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

public var NSFileWriteNoPermissionError: Int { get } // Write error (permission problem) public var NSFileWriteInvalidFileNameError: Int { get } // Write error (invalid file name)public var NSFileWriteFileExistsError: Int { get } // Write error (file exists)public var NSFileWriteInapplicableStringEncodingError: Int { get } // Write error (string encoding not applicable) also NSStringEncodingErrorKey public var NSFileWriteUnsupportedSchemeError: Int { get } // Write error (unsupported URL scheme) public var NSFileWriteOutOfSpaceError: Int { get } // Write error (out of disk space) public var NSFileWriteVolumeReadOnlyError: Int { get } // Write error (readonly volume)

// NSFileManager unmount errors public var NSFileManagerUnmountUnknownError: Int { get } // The volume could not be unmounted (reason unknown) public var NSFileManagerUnmountBusyError: Int { get } // The volume could not be unmounted because it is in use

Page 159: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

// Other errors public var NSKeyValueValidationError: Int { get } // KVC validation errorpublic var NSFormattingError: Int { get } // Formatting errorpublic var NSUserCancelledError: Int { get } // User cancelled operation (this one often doesn't deserve a panel and might be a good one to special case) public var NSFeatureUnsupportedError: Int { get } // Feature unsupported error

// Executable loading errors public var NSExecutableNotLoadableError: Int { get } // Executable is of a type that is not loadable in the current process public var NSExecutableArchitectureMismatchError: Int { get } // Executable does not provide an architecture compatible with the current process public var NSExecutableRuntimeMismatchError: Int { get } // Executable has Objective C runtime information incompatible with the current process public var NSExecutableLoadError: Int { get } // Executable cannot be loaded for some other reason, such as a problem with a library it depends on public var NSExecutableLinkError: Int { get } // Executable fails due to linking issues

Page 160: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

throw NSError(domain: NSCocoaErrorDomain, code: NSFileReadCorruptFileError, userInfo: [ NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Re-download the file and try again.", comment: "Recovery suggestion when importing file via download."), NSURLErrorKey: fileURL])

Page 161: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

throw NSError(domain: NSCocoaErrorDomain, code: NSFileReadCorruptFileError, userInfo: [ NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Re-download the file and try again.", comment: "Recovery suggestion when importing file via download."), NSURLErrorKey: fileURL])

Page 162: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

throw CocoaError.error(.fileReadCorruptFile, userInfo: [ NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Re-download the file and try again.", comment: "Recovery suggestion when importing file via download."), NSURLErrorKey: fileURL])

NEW

Page 163: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

throw CocoaError.error(.fileReadCorruptFile, userInfo: [ NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Re-download the file and try again.", comment: "Recovery suggestion when importing file via download."), NSURLErrorKey: fileURL])

NEW

Page 164: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSError

Page 165: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSError

Page 166: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

struct CatError { public static var domain = "CatErrorDomain" public enum code : Int { case notFound case busyEating case meowingAtWall case attackingDust }} throw NSError(domain: CatError.domain, code: CatError.code.meowingAtWall.rawValue, userInfo: [ NSLocalizedFailureErrorKey: NSLocalizedString("Cat is sitting in the corner meowing at the wall.", comment:"Failure message when cat is meowing at wall"), NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Confuse the cat and try again later", comment:"Recovery suggestion when cat is meowing at wall"),])

Page 167: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

struct CatError { public static var domain = "CatErrorDomain" public enum code : Int { case notFound case busyEating case meowingAtWall case attackingDust }} throw NSError(domain: CatError.domain, code: CatError.code.meowingAtWall.rawValue, userInfo: [ NSLocalizedFailureErrorKey: NSLocalizedString("Cat is sitting in the corner meowing at the wall.", comment:"Failure message when cat is meowing at wall"), NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Confuse the cat and try again later", comment:"Recovery suggestion when cat is meowing at wall"),])

Page 168: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

struct CatError { public static var domain = "CatErrorDomain" public enum code : Int { case notFound case busyEating case meowingAtWall case attackingDust }} throw NSError(domain: CatError.domain, code: CatError.code.meowingAtWall.rawValue, userInfo: [ NSLocalizedFailureErrorKey: NSLocalizedString("Cat is sitting in the corner meowing at the wall.", comment:"Failure message when cat is meowing at wall"), NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Confuse the cat and try again later", comment:"Recovery suggestion when cat is meowing at wall"),])

Page 169: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

struct CatError { public static var domain = "CatErrorDomain" public enum code : Int { case notFound case busyEating case meowingAtWall case attackingDust }} throw NSError(domain: CatError.domain, code: CatError.code.meowingAtWall.rawValue, userInfo: [ NSLocalizedFailureErrorKey: NSLocalizedString("Cat is sitting in the corner meowing at the wall.", comment:"Failure message when cat is meowing at wall"), NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Confuse the cat and try again later", comment:"Recovery suggestion when cat is meowing at wall"),])

Page 170: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

struct CatError { public static var domain = "CatErrorDomain" public enum code : Int { case notFound case busyEating case meowingAtWall case attackingDust }} throw NSError(domain: CatError.domain, code: CatError.code.meowingAtWall.rawValue, userInfo: [ NSLocalizedFailureErrorKey: NSLocalizedString("Cat is sitting in the corner meowing at the wall.", comment:"Failure message when cat is meowing at wall"), NSLocalizedRecoverySuggestionErrorKey: NSLocalizedString("Confuse the cat and try again later", comment:"Recovery suggestion when cat is meowing at wall"),])

Page 171: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSError.setUserInfoValueProvider(forDomain: CatError.domain) { (error: Error, key) -> Any? in let errorCode = CatError.code(rawValue:(error as NSError).code)! switch (key) { case NSLocalizedFailureErrorKey: switch (errorCode) { case .notFound: return NSLocalizedString("Cat not found.", comment: "Failure message when the cat is not found.") case .meowingAtWall:

return NSLocalizedString("Cat is sitting in the corner meowing at the wall.", comment:"Failure message when cat is meowing at wall") … … }})

throw NSError(domain: CatError.domain, code: CatError.meowingAtWall.rawValue)

Page 172: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSError.setUserInfoValueProvider(forDomain: CatError.domain) { (error: Error, key) -> Any? in let errorCode = CatError.code(rawValue:(error as NSError).code)! switch (key) { case NSLocalizedFailureErrorKey: switch (errorCode) { case .notFound: return NSLocalizedString("Cat not found.", comment: "Failure message when the cat is not found.") case .meowingAtWall:

return NSLocalizedString("Cat is sitting in the corner meowing at the wall.", comment:"Failure message when cat is meowing at wall") … … }})

throw NSError(domain: CatError.domain, code: CatError.meowingAtWall.rawValue)

Page 173: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSError.setUserInfoValueProvider(forDomain: CatError.domain) { (error: Error, key) -> Any? in let errorCode = CatError.code(rawValue:(error as NSError).code)! switch (key) { case NSLocalizedFailureErrorKey: switch (errorCode) { case .notFound: return NSLocalizedString("Cat not found.", comment: "Failure message when the cat is not found.") case .meowingAtWall:

return NSLocalizedString("Cat is sitting in the corner meowing at the wall.", comment:"Failure message when cat is meowing at wall") … … }})

throw NSError(domain: CatError.domain, code: CatError.meowingAtWall.rawValue)

Page 174: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSError.setUserInfoValueProvider(forDomain: CatError.domain) { (error: Error, key) -> Any? in let errorCode = CatError.code(rawValue:(error as NSError).code)! switch (key) { case NSLocalizedFailureErrorKey: switch (errorCode) { case .notFound: return NSLocalizedString("Cat not found.", comment: "Failure message when the cat is not found.") case .meowingAtWall:

return NSLocalizedString("Cat is sitting in the corner meowing at the wall.", comment:"Failure message when cat is meowing at wall") … … }})

throw NSError(domain: CatError.domain, code: CatError.meowingAtWall.rawValue)

Page 175: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

NSError.setUserInfoValueProvider(forDomain: CatError.domain) { (error: Error, key) -> Any? in let errorCode = CatError.code(rawValue:(error as NSError).code)! switch (key) { case NSLocalizedFailureErrorKey: switch (errorCode) { case .notFound: return NSLocalizedString("Cat not found.", comment: "Failure message when the cat is not found.") case .meowingAtWall:

return NSLocalizedString("Cat is sitting in the corner meowing at the wall.", comment:"Failure message when cat is meowing at wall") … … }})

throw NSError(domain: CatError.domain, code: CatError.meowingAtWall.rawValue)

Page 176: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

open class NSError : NSObject, NSCopying, NSSecureCoding {

/* Return titles of buttons that are appropriate for displaying in an alert. These should match the string provided as a part of localizedRecoverySuggestion. The first string would be the title of the right-most and default button, the second one next to it, and so on. … */ open var localizedRecoveryOptions: [String]? { get }

/* Return an object that conforms to the NSErrorRecoveryAttempting informal protocol. The recovery attempter must be an object that can correctly interpret an index into the array returned by localizedRecoveryOptions. …. */ open var recoveryAttempter: Any? { get }

}

Page 177: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

open class NSError : NSObject, NSCopying, NSSecureCoding {

/* Return titles of buttons that are appropriate for displaying in an alert. These should match the string provided as a part of localizedRecoverySuggestion. The first string would be the title of the right-most and default button, the second one next to it, and so on. … */ open var localizedRecoveryOptions: [String]? { get }

/* Return an object that conforms to the NSErrorRecoveryAttempting informal protocol. The recovery attempter must be an object that can correctly interpret an index into the array returned by localizedRecoveryOptions. …. */ open var recoveryAttempter: Any? { get }

}

Page 178: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

public let NSLocalizedRecoveryOptionsErrorKey: String // NSArray of NSStrings corresponding to button titles.

public let NSRecoveryAttempterErrorKey: String // Instance of a subclass of NSObject that conforms to the NSErrorRecoveryAttempting informal protocol

Page 179: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Shared Key Sets

6

Page 180: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSDictionary {

open class func sharedKeySet(forKeys: [NSCopying]) -> Any

}

extension NSMutableDictionary {

public init(sharedKeySet: Any) }

Page 181: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSDictionary {

open class func sharedKeySet(forKeys: [NSCopying]) -> Any

}

extension NSMutableDictionary {

public init(sharedKeySet: Any) }

Page 182: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSDictionary {

open class func sharedKeySet(forKeys: [NSCopying]) -> Any

}

extension NSMutableDictionary {

public init(sharedKeySet: Any) }

Page 183: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSDictionary {

open class func sharedKeySet(forKeys: [NSCopying]) -> Any

}

extension NSMutableDictionary {

public init(sharedKeySet: Any) }

Page 184: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let catKeySet = NSDictionary.sharedKeySet(forKeys: [ NSString(string:"Name"), NSString(string:"Photo"), NSString(string:"Status")])

let cat = NSMutableDictionary(sharedKeySet: catKeySet) cat["Name"] = "Pixel" cat["Status"] = "Meowing at wall" cat["FavoriteCorner"] = "North-West" // Not as efficient, but works!

Page 185: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let catKeySet = NSDictionary.sharedKeySet(forKeys: [ NSString(string:"Name"), NSString(string:"Photo"), NSString(string:"Status")])

let cat = NSMutableDictionary(sharedKeySet: catKeySet) cat["Name"] = "Pixel" cat["Status"] = "Meowing at wall" cat["FavoriteCorner"] = "North-West" // Not as efficient, but works!

Page 186: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let catKeySet = NSDictionary.sharedKeySet(forKeys: [ NSString(string:"Name"), NSString(string:"Photo"), NSString(string:"Status")])

let cat = NSMutableDictionary(sharedKeySet: catKeySet) cat["Name"] = "Pixel" cat["Status"] = "Meowing at wall" cat["FavoriteCorner"] = "North-West" // Not as efficient, but works!

Page 187: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let catKeySet = NSDictionary.sharedKeySet(forKeys: [ NSString(string:"Name"), NSString(string:"Photo"), NSString(string:"Status")])

let cat = NSMutableDictionary(sharedKeySet: catKeySet) cat["Name"] = "Pixel" cat["Status"] = "Meowing at wall" cat["FavoriteCorner"] = "North-West" // Not as efficient, but works!

Page 188: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let catKeySet = NSDictionary.sharedKeySet(forKeys: [ NSString(string:"Name"), NSString(string:"Photo"), NSString(string:"Status")])

let cat = NSMutableDictionary(sharedKeySet: catKeySet) cat["Name"] = "Pixel" cat["Status"] = "Meowing at wall" cat["FavoriteCorner"] = "North-West" // Not as efficient, but works!

Page 189: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

let catKeySet = NSDictionary.sharedKeySet(forKeys: [ NSString(string:"Name"), NSString(string:"Photo"), NSString(string:"Status")])

let cat = NSMutableDictionary(sharedKeySet: catKeySet) cat["Name"] = "Pixel" cat["Status"] = "Meowing at wall" cat["FavoriteCorner"] = "North-West" // Not as efficient, but works!

Page 190: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Accessibility

0xa

Page 191: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Accessibility VoiceOver

VoiceOver information is easy to add in Interface Builder

VoiceOver comes built-in on Apple products

Page 192: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Accessibility VoiceOver

Page 193: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Accessibility Screen resolution

Test at 1024 x 640

Page 194: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 195: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 196: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Accessibility Accessibility Inspector in Xcode

Page 197: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Documents

Page 198: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Document-based App

Page 199: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Document-based App

Page 200: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Document-based App

Page 201: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Document-based App NEW

Page 202: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Use NSDocument!

Page 203: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

open class NSDocument : … { open class var autosavesInPlace: Bool { get } }

Page 204: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

open class NSDocument : … { open class var autosavesInPlace: Bool { get } }

Page 205: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class MyDocument : NSDocument { override class var autosavesInPlace { return true }

}

Page 206: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

class MyDocument : NSDocument { override class var autosavesInPlace { return true }

}

Page 207: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Reporting Exceptions

42

Page 208: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

open class NSApplication : NSResponder, … {

open func reportException(_ exception: NSException) }

Page 209: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

open class NSApplication : NSResponder, … {

open func reportException(_ exception: NSException) }

Page 210: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Debugging Modes in Xcode

NaN

Page 211: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Xcode Debugging Modes

Page 212: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Xcode Debugging Modes

Debug view hierarchy

Page 213: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Xcode Debugging Modes

Debug view hierarchy

Debug memory graph

Page 214: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Xcode Debugging Modes

Debug view hierarchy

Debug memory graph

Simulate location

Page 215: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Xcode Debugging Modes

Debug view hierarchy

Debug memory graph

Simulate location

Page 216: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 217: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 218: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 219: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Write Bug Reports

30512012

Page 220: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

How to Make Your Bug Reports Easier to Fix https://bugreport.apple.com/

Page 221: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

How to Make Your Bug Reports Easier to Fix https://bugreport.apple.com/

Include steps to reproduce

Page 222: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

How to Make Your Bug Reports Easier to Fix https://bugreport.apple.com/

Include steps to reproduce

Include a sample app that builds and shows the problem

Page 223: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

How to Make Your Bug Reports Easier to Fix https://bugreport.apple.com/

Include steps to reproduce

Include a sample app that builds and shows the problem

Include any resources (image, database, etc.) that might be needed

Page 224: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

How to Make Your Bug Reports Easier to Fix https://bugreport.apple.com/

Include steps to reproduce

Include a sample app that builds and shows the problem

Include any resources (image, database, etc.) that might be needed

Attach a sysdiagnose or other logs

Page 225: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

How to Make Your Bug Reports Easier to Fix https://bugreport.apple.com/

Include steps to reproduce

Include a sample app that builds and shows the problem

Include any resources (image, database, etc.) that might be needed

Attach a sysdiagnose or other logs• https://developer.apple.com/bug-reporting/profiles-and-logs/

Page 226: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

How to Make Your Radars Easier to Fix https://bugreport.apple.com/

Page 227: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Bells and Whistles

44.1

Page 228: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSButton { open var sound: NSSound?

}

Page 229: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSButton { open var sound: NSSound?

}

Page 230: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSButton { open var sound: NSSound?

}

Page 231: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

extension NSButton { open var sound: NSSound?

}

Page 232: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Demo

29

Page 233: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 234: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Add Your Own Tips

N+1

Page 235: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

New Documentation https://developer.apple.com/documentation

Page 236: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

New Documentation https://developer.apple.com/documentation

Topics grouped by task

Page 237: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

New Documentation https://developer.apple.com/documentation

Topics grouped by task

Hierarchical structure

Page 238: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

New Documentation https://developer.apple.com/documentation

Topics grouped by task

Hierarchical structure

Example:

Page 239: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

New Documentation https://developer.apple.com/documentation

Topics grouped by task

Hierarchical structure

Example:

Page 240: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

New Documentation https://developer.apple.com/documentation

Page 241: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

New Documentation https://developer.apple.com/documentation

Reference

Page 242: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

New Documentation https://developer.apple.com/documentation

Reference

Conceptual

Page 243: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

New Documentation https://developer.apple.com/documentation

Reference

Conceptual

Sample Code

Page 244: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

New Documentation https://developer.apple.com/documentation

Reference

Conceptual

Sample Code

Page 245: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Release Notes https://developer.apple.com/library/content/releasenotes/AppKit/RN-AppKit/index.html

Page 246: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

/* NSImage.h Application Kit Copyright (c) 1994-2017, Apple Inc. All rights reserved. */

...

// Note that the block passed to the below method may be invoked whenever and on whatever thread the image itself is drawn on. Care should be taken to ensure that all state accessed within the drawingHandler block is done so in a thread safe manner. + (NSImage *)imageWithSize:(NSSize)size flipped:(BOOL)drawingHandlerShouldBeCalledWithFlippedContext drawingHandler: (BOOL (^)(NSRect dstRect))drawingHandler NS_AVAILABLE_MAC(10_8);

...

Page 247: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Tweet Your Tips!Use #WWDC17 and #cocoatip

Page 248: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 249: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 250: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

typealias StringDict = Dictionary<String, String>

var a: StringDict = [:]

a = ["b": "c"]

Page 251: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 252: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 253: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Quick Look Expression

Page 254: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Quick Look Expression

Page 255: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Quick Look Expression

Page 256: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Quick Look Expression

Page 257: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Quick Look Expression

Page 258: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Quick Look Expression

Page 259: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Quick Look Expression

Page 260: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Quick Look Expression

Page 261: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Quick Look Expression

Page 262: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Quick Look Expression

Page 263: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

More Informationhttps://developer.apple.com/wwdc17/236

Page 264: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Related Sessions

Localizing with Xcode 9 WWDC 2017

What’s New in Swift WWDC 2017

What's New in Cocoa WWDC 2017

What's New in Core Data WWDC 2017

What's New in Foundation WWDC 2017

What's New in Accessibility WWDC 2017

Page 265: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}

Labs

Cocoa Lab Technology Lab B Fri 1:50PM–3:20PM

Page 266: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}
Page 267: Twenty-nine things you may not know about Co coa var backgroundColor = NSColor.clear override func updateLayer() {layer?.backgroundColor = backgroundColor.cgColor}}