macOS development from
iOS developer’s perspective
Serhii Bykov
macOS Developer, Setapp
1
Slide 2
Slide 2 text
Agenda
• What’s similar
• What’s different
• What’s unique for macOS
2
Slide 3
Slide 3 text
Intro
3
Slide 4
Slide 4 text
Who am I
• 5+ years of iOS Development
• ≈ 10 different projects
• 6 months of macOS Development
4
Slide 5
Slide 5 text
Why did I switch to macOS
• All my iOS projects were not so big
• Most of the time I was the only one iOS developer in a team
• I thought there were more challenging tasks in macOS development
5
Slide 6
Slide 6 text
❓ Why am I giving this talk
• Cocoa community is big and it keeps growing
• 90-95% people of Cocoa community are iOS developers
• I am still struggling while developing for macOS
• So I’ve decided to provide an easy ramp-up for iOS developers to
start developing for macOS
6
Slide 7
Slide 7 text
Technical comparison
7
Slide 8
Slide 8 text
♊ What’s similar
8
Slide 9
Slide 9 text
♊ What’s similar
• Environment
• Frameworks
• Classes
9
♊ What’s similar - Frameworks
• Foundation
• Core Animation
• Core Graphics
• Core Text
• Core Data
• libdispatch
• etc.
11
Slide 12
Slide 12 text
♊ What’s similar - UI frameworks
• UIKit - lightweight version of AppKit
• UIKit & AppKit are sharing a lot of concepts
12
Slide 13
Slide 13 text
♊ What’s similar - UI frameworks - Class names
13
UIKit AppKit
UIWindow NSWindow
UIViewController NSViewController
UIView NSView
UIResponder NSResponder
Slide 14
Slide 14 text
14
Isn’t it enough to replace UI with NS
in your iOS app to get macOS app?
Slide 15
Slide 15 text
15
Slide 16
Slide 16 text
What’s different
16
Slide 17
Slide 17 text
What’s different
• Windows
• Views
• Collections
• Images
• Colors
• Restrictions
17
Slide 18
Slide 18 text
Windows
18
Slide 19
Slide 19 text
UIWindow vs NSWindow
• UIWindow - cannot be modified, since it takes up the whole screen
• NSWindow - can be resized, zoomed, minimised, hidden, closed, etc.
19
Windows - Parent Class
21
@interface NSWindow : NSResponder
@interface UIWindow : UIView
Slide 22
Slide 22 text
Views
22
Slide 23
Slide 23 text
Views
• View system works very differently on the Mac
• On iOS, views were backed by Core Animation layers by default
• AppKit integrated Core Animation into views much later
23
Layer-Backed Views
• A layer-backed view is a view that is backed by a Core Animation layer
• Any drawing done by the view is cached to the underlying layer
object
• You should never interact directly with the layer
25
Layer-Hosting View
• A layer-hosting view is a view that contains a Core Animation layer that
you intend to manipulate directly
• You are responsible for managing the view’s layer
• Do not rely on the view for drawing
• Do not add subviews
29
Layer-Hosting View - Why
31
• Why would one create a layer-hosting view?
• When you need some advanced operations with layer or when you
want to configure a hierarchy of layers associated with a single view
Slide 32
Slide 32 text
Views - Different Kinds - Recap
32
• Layer-Backed Views
• Basic operations with views
• Layer-Hosting Views
• Advanced operations that need some manipulations with layer
Slide 33
Slide 33 text
⚙ Other View-Related Gotchas
• Coordinate system
• Listening mouse events
• Label
• NSCell
33
Slide 34
Slide 34 text
UIKit coordinate system
34
(0; 0)
Slide 35
Slide 35 text
AppKit coordinate system
35
(0; 0)
Slide 36
Slide 36 text
Fix AppKit coordinate system
class FlippedView: NSView {
override var isFlipped: Bool {
return true
}
}
36
Slide 37
Slide 37 text
Receiving events from mouse
class MouseTrackingView: NSView {
override func mouseMoved(with event: NSEvent) {
// this method won't be called
}
}
37
Slide 38
Slide 38 text
Receiving events from mouse
class MouseTrackingView: NSView {
private var trackingArea: NSTrackingArea?
override func mouseMoved(with event: NSEvent) {
// now this method will be called
}
override func updateTrackingAreas() {
if let area = trackingArea { removeTrackingArea(area) }
let options: NSTrackingArea.Options = [.mouseMoved, .activeAlways]
let area = NSTrackingArea(rect: bounds, options: options, owner:
self, userInfo: nil)
addTrackingArea(area)
self.trackingArea = area
}
}
38
Slide 39
Slide 39 text
Label
• In AppKit there’s no such class as NSLabel
39
let label = NSTextField()
label.drawsBackground = false
label.isBezeled = false
label.isEditable = false
label.isSelectable = false
Slide 40
Slide 40 text
NSCell
• AppKit controls have been traditionally backed by NSCell subclasses
• NSCell ≠ NSTableCellView ≠ NSCollectionCellView
• Apple is deprecating this approach
40
Slide 41
Slide 41 text
⚙ NSCell - Poor Little Bryan
41
Slide 42
Slide 42 text
Collections
42
Slide 43
Slide 43 text
Collections - Common
• No scroll view by default
• You had to install your NSTableView or NSCollectionView to
NSScrollView via documentView property
43
Slide 44
Slide 44 text
Collections - NSTableView
• Columns
• Cells
44
Slide 45
Slide 45 text
NSTableView - Columns
45
Slide 46
Slide 46 text
NSTableView - Different cell classes
• NSTableView can present the following objects
• NSCell subclasses
• NSTableCellView subclasses
46
Slide 47
Slide 47 text
NSTableView - NSCell-based
47
Slide 48
Slide 48 text
NSTableView - NSView-based
48
Slide 49
Slide 49 text
NSCell-based vs NSView-based
49
• NSCell-based - when you don’t need more than 1 control in cell
• NSView-based - all other cases
Slide 50
Slide 50 text
Images
50
Slide 51
Slide 51 text
NSImage
• NSImage is more powerful than UIImage
51
NSImage
UIImage
Slide 52
Slide 52 text
NSImage - Key Differences
• NSImage can be backed by one or more image representations
• NSImageRep - representations for BMP, EPS, PDF, etc
• NSImage will cache the result when it’s drawn to the screen
52
Slide 53
Slide 53 text
Colors
53
Slide 54
Slide 54 text
Colors
• macOS supports fully color-calibrated workflows, so anything having to
do with colors is potentially more complicated
• A common task is to use a color in your app that your designers have
specified for you
• Make sure you’re using same color space for Xcode &
54
Slide 55
Slide 55 text
Restrictions
55
Slide 56
Slide 56 text
Restrictions
• Sandboxing
• Permissions
56
Slide 57
Slide 57 text
Sandboxing - What is Sandbox
57
Slide 58
Slide 58 text
Sandboxing - Limitations
A sandboxed app must explicitly state its intent to use any of the
following resources
58
• Hardware (, , )
• Network Connections (⬆, ⬇)
• App Data (, , )
• User Files (, , , , )
Slide 59
Slide 59 text
59
macOS sandbox = iOS sandbox?
Slide 60
Slide 60 text
Sandboxing - Mac App Store
• Apps distributed through the Mac App Store must adopt App Sandbox.
• Apps signed and distributed outside of the Mac App Store with
Developer ID can use App Sandbox as well.
60
Slide 61
Slide 61 text
Can we do whatever we want?
61
Slide 62
Slide 62 text
62
Slide 63
Slide 63 text
Permissions - Pre-Catalina
• Calendar, Reminders - 10.9
• Contacts - 10.11
• Photos - 10.13
• Full Disk Access - 10.14
63
Cocoa Bindings - What are they
• Cocoa bindings technology provides a way of keeping model and view
values synchronised
95
Slide 96
Slide 96 text
Bindings - Basic Example
• Text Field text content changes string variable
• String variable changes Text Field text content
96
Slide 97
Slide 97 text
NSTextField - Enable binding
97
Slide 98
Slide 98 text
NSTextField - 0 LoC binding
98
Slide 99
Slide 99 text
99
NSTextField - 0 LoC binding
Slide 100
Slide 100 text
Bindings - NSController & subclasses
The other key part of Cocoa Bindings is the abstract class NSController
and its 3 subclasses
• NSObjectController
• NSArrayController
• NSTreeController
100
Bindings - PONSO Model
class Speaker : NSObject {
@objc dynamic var firstName : String = ""
@objc dynamic var lastName : String = ""
init(firstName: String, lastName: String) {
super.init()
self.firstName = firstName
self.lastName = lastName
}
}
102
Slide 103
Slide 103 text
NSViewController - Sample Data
class ViewController: NSViewController {
@objc dynamic var speakers: [Speaker] = [
Speaker(firstName: "Serhii", lastName: "Bykov"),
Speaker(firstName: "Sergey", lastName:
"Krivoblotsky"),
Speaker(firstName: "Bohdan", lastName:
"Mihiliev"),
]
}
103
Slide 104
Slide 104 text
Bindings - Add NSArrayController
104
Slide 105
Slide 105 text
Bind NSArrayController to NSTableView
105
Slide 106
Slide 106 text
Bind NSArrayController to NSTableView
106
Slide 107
Slide 107 text
Bind NSArrayController to NSViewController
107
Slide 108
Slide 108 text
Bind properties to cells
108
Slide 109
Slide 109 text
Bind properties to cells
109
Slide 110
Slide 110 text
NSTableView w/ data (0 LoC)
110
Slide 111
Slide 111 text
Interaction with a system
111
Slide 112
Slide 112 text
Interaction with a system
• NSWorkspace
• NSRunningApplication
• NSTask / Process
112
Slide 113
Slide 113 text
NSWorkspace
A workspace that can launch other apps and perform a variety of file-
handling services
• File operations
• System operations
113
Slide 114
Slide 114 text
NSWorkspace - Files Operations
• Open files & URLs
• Duplicating files ♊
• Moving files to the trash
• Revealing a file location in Finder
• Getting icons for files
114
Slide 115
Slide 115 text
NSWorkspace - System Operations
• Launching an application ⬇
• Hiding all other applications
• Getting a list of all running apps or the frontmost app
• Get or modify the Desktop picture
• etc.
115
NSTask / Process
• NSTask run another program as a process
• Apple API are feature-rich, but sometimes all you need is some
command line tool
• Some apps are just GUI shells for command line tools (e.g. any git
clients)
117
Slide 118
Slide 118 text
More and more
• Documents
• Background processes
• Cross-process communication
• AppleScript
• Plugin Infrastructure
• etc.
118
Slide 119
Slide 119 text
Catalyst
119
Slide 120
Slide 120 text
Catalyst - Pros
• New framework
• Code sharing
• Development pace
120
Slide 121
Slide 121 text
Catalyst - Cons
• New framework
• You will still need to write a platform-specific code
• macOS 10.15+
121
macOS Adoption Rate
• Mojave - 33.49%
• Catalina - 27.12%
• High Sierra - 17.11%
• Sierra - 8.2%
• Other - 14.1%
Data: https://gs.statcounter.com/macos-version-market-share/desktop/worldwide/#monthly-201911-201911-bar
Other
14%
Sierra
8%
High Sierra
17%
Catalina
27%
Mojave
33%
123
Slide 124
Slide 124 text
Catalyst - Wrap Up
• Catalyst can wait till it becomes stable and more users will update to
Catalina
• It is still worth trying since it’s a good way to try a lil bit of desktop
development
124
Slide 125
Slide 125 text
Conclusions
125
Slide 126
Slide 126 text
Conclusions
• All missing API’s will be probably covered by code written by your
colleagues
• Despite all the differences between platforms, your daily development
process will look pretty close to your iOS tasks, if you’re not doing
something extraordinary
• Setapp will soon have iOS application, so feel free to apply to us
• https://macpaw.com/careers/macos-setapp
126