Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently...
Transcript of Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently...
![Page 1: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/1.jpg)
WWDC17
copy 2017 Apple Inc All rights reserved Redistribution or public display not permitted without written permission from Apple
Philippe Hausler Foundation Donna Tom TextKit
bullEfficient Interaction with Frameworks bullPerformance case studies bull Session 244
App Frameworks
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
Improvements in Foundation
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 2: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/2.jpg)
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
Improvements in Foundation
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 3: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/3.jpg)
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
Improvements in Foundation
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 4: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/4.jpg)
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
Improvements in Foundation
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 5: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/5.jpg)
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
I
IVIII
II
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
Improvements in Foundation
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 6: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/6.jpg)
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
Improvements in Foundation
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 7: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/7.jpg)
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
Improvements in Foundation
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 8: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/8.jpg)
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
Improvements in Foundation
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 9: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/9.jpg)
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
Improvements in Foundation
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 10: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/10.jpg)
bullImprovements in Foundation bullBridges and how they affect your app bullStrings ranges and text
Improvements in Foundation
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 11: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/11.jpg)
Improvements in Foundation
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 12: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/12.jpg)
Improvements in Foundation
NSCalendar
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 13: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/13.jpg)
Improvements in Foundation
NSCalendar
Internal locking improvements
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 14: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/14.jpg)
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 15: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/15.jpg)
Improvements in Foundation
NSCalendar
Internal locking improvements
NSOperation and NSOperationQueue
Copy on write collections
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 16: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/16.jpg)
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 17: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/17.jpg)
Copy on Write Collections There is a CoW level
What is copy on write
How does it work
How can I improve my code to work better and safer with it
implementation Container
NSMutableArrayltItem gt _elements
- (NSArrayltItem gt )elements
return [_elements copy]
end
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 18: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/18.jpg)
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 19: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/19.jpg)
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 20: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/20.jpg)
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 21: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/21.jpg)
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 22: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/22.jpg)
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 23: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/23.jpg)
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 24: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/24.jpg)
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 25: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/25.jpg)
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 26: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/26.jpg)
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 27: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/27.jpg)
Copy on Write Collections Letrsquos milk this joke a bit more
a = [NSMutableArray new] a 128004 []
128004 []b = [a copy] a
b
[a addObjectA]
a
b
128004 [A]
128004 []
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 28: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/28.jpg)
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 29: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/29.jpg)
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 30: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/30.jpg)
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 31: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/31.jpg)
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 32: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/32.jpg)
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 33: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/33.jpg)
Leveraging Copy-on-write Steer your code in the right direction WARNING Donrsquot pass any NSMutableArrays into hereproperty (strong) NSArrayltItem gt items
Copies are saferproperty (copy) NSArrayltItem gt items
- (NSArrayltItem gt )items NSMutableArray items = [[NSMutableArray alloc] init] [self buildItemsitems] WARNING Dont mutate this it is declared as NSArray so it should be safe return items
This will copyaNSArray as [Any]
The copy is completely safe here and also is nearly free so avoid bad things later return [items copy]
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 34: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/34.jpg)
Data The best type for dealing with bytes
Data is its own slice
Indexing is only a few instructions in optimized builds
Appending is dramatically faster
Replacing regions is faster too
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 35: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/35.jpg)
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 36: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/36.jpg)
Subscripting Data
func findZeroByte(_ data Data) -gt DataIndex
for index in dataindices
if data[index] == 0 return index
return nil
Nan
osec
onds
02468
1012141618
Samples
Swift 3Swift 4
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 37: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/37.jpg)
Leveraging Data Donrsquot Believe the Lore
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 38: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/38.jpg)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 39: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/39.jpg)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 40: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/40.jpg)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 41: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/41.jpg)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 42: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/42.jpg)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 43: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/43.jpg)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 44: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/44.jpg)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 45: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/45.jpg)
Leveraging Data Donrsquot Believe the Lore
var bytes [UInt8] = [0xcf 0xfa 0xed 0xfe]var bytes = Data(bytes [0xcf 0xfa 0xed 0xfe])
var buffer = malloc(250)assumingMemoryBound(to UInt8self)defer free(buffer) var buffer = Data(count 250)
let header = buffersubdata(in bufferstartIndexltbufferstartIndexadvanced(by 4))
let header = buffer[ltbufferstartIndexadvanced(by 4)]
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 46: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/46.jpg)
Bridges and How They Impact Your App For whom the bridge tolls
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 47: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/47.jpg)
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridging
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 48: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/48.jpg)
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 49: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/49.jpg)
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 50: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/50.jpg)
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at cast
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 51: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/51.jpg)
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 52: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/52.jpg)
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridges
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 53: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/53.jpg)
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a struct
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 54: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/54.jpg)
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference type
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 55: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/55.jpg)
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advance
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 56: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/56.jpg)
Bridges and How They Impact Your App For whom the bridge tolls
Toll-free bridgingbull From a CF type to a NS typebull From a NS type to a CF typebull Zero cost at castbull Extra cost at usage
Swift bridgesbull From a reference type to a structbull From a struct to a reference typebull Cost is paid in advancebull Normal cost at usage
NSArray array = []
CFArrayGetCount((CFArrayRef)array)let data = NSData()
let d = data as Data
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 57: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/57.jpg)
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 58: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/58.jpg)
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 59: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/59.jpg)
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) CF_OBJC_FUNCDISPATCHV(CFArrayGetTypeID() CFIndex (NSArray )array count) return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 60: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/60.jpg)
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (CF_IS_OBJC(CFArrayGetTypeID() array) return [(NSArray )obj count] return array-gtcount
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 61: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/61.jpg)
CF Bridging
CFIndex CFArrayGetCount(CFArrayRef array) if (object_getClass(array) = CFClasses[CFArrayGetTypeID()]) return [(NSArray )obj count] return array-gtcount
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 62: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/62.jpg)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 63: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/63.jpg)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 64: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/64.jpg)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 65: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/65.jpg)
CF Bridging
NSArray array = [] CFArrayGetCount((CFArrayRef)array)
Small and Unknown Frequency
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 66: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/66.jpg)
Swift Bridging
extension Data _ObjectiveCBridgeable hellip public static func _conditionallyBridgeFromObjectiveC(_ input NSData result inout Data) -gt Bool We must copy the input because it might be mutable just like storing a value type in ObjC result = Data(referencing input) return true hellip
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 67: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/67.jpg)
Swift Bridging
struct Data hellip public init(referencing reference NSData) _backing = _DataStorage(immutableReference referencecopy() as NSData) _sliceRange = 0ltreferencelength hellip
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 68: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/68.jpg)
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 69: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/69.jpg)
Swift Bridging
let data = NSData() let d = data as Data
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 70: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/70.jpg)
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 71: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/71.jpg)
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 72: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/72.jpg)
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 73: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/73.jpg)
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 74: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/74.jpg)
Swift Bridging
let data = NSData() let d = data as Data
Usually small and infrequenthellip
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 75: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/75.jpg)
Donna Tom TextKit
bullStrings Ranges and Text
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 76: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/76.jpg)
Strings are everywhere
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 77: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/77.jpg)
Invest in performancethat matters to your users
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 78: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/78.jpg)
Frequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 79: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/79.jpg)
$
cent
measure
measure
I
IVIII
II
Short Length Long Length
Runs Frequently
Runs Infrequently
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 80: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/80.jpg)
bullString bridging bullRanges bullText layout and rendering
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 81: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/81.jpg)
bullString bridging bullRanges bullText layout and rendering
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 82: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/82.jpg)
Example 1 UILabel
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 83: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/83.jpg)
String Bridging Example 1 UILabel
Swift var text = labeltext
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 84: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/84.jpg)
String Bridging Example 1 UILabel
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 85: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/85.jpg)
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 86: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/86.jpg)
String Bridging Example 1 UILabel
Objective-C - UIKit
interface UILabel UIView
property(nullable nonatomic copy) NSString text
bridge
Swift Interface - UIKit open class UILabel UIView open var text String
Swift var text = labeltext
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 87: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/87.jpg)
String Bridging Example 1 UILabel
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 88: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/88.jpg)
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 89: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/89.jpg)
String Bridging Example 1 UILabel
Swift Framework
class NSString struct String class NSString
var text = labeltext
copy
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 90: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/90.jpg)
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 91: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/91.jpg)
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltext I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 92: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/92.jpg)
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = labeltextcent I
IVIII
II
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 93: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/93.jpg)
Example 2 NSTextStorage
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 94: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/94.jpg)
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 95: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/95.jpg)
pretend there is a lot of text here Irsquod like to get an animation of a scrolling
text view with lots of text
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 96: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/96.jpg)
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 97: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/97.jpg)
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 98: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/98.jpg)
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Swift Interface - UIKit
class NSTextStorage NSMutableAttributedString
open class NSMutableAttributedString
NSAttributedString
open var string NSString
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 99: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/99.jpg)
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 100: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/100.jpg)
String Bridging Example 2 NSTextStorage
Swift
var text = textViewtextStoragestring
Objective-C - UIKit
interface NSTextStorage NSMutableAttributedString
Objective-C - Foundation
interface NSMutableAttributedString
NSAttributedString
property(readonly copy) NSString string
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 101: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/101.jpg)
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragestring
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 102: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/102.jpg)
String Bridging Example 2 NSTextStorage
Swift Framework
class NSString struct String class NSString
var text = textViewtextStoragestring
copy
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 103: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/103.jpg)
String Bridging Example 2 NSTextStorage
var text = textViewtextStoragemutableString
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 104: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/104.jpg)
String Bridging Example 2 NSTextStorage
Swift Framework
class NSMutableString
var text = textViewtextStoragemutableString
no copyclass NSMutableString
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 105: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/105.jpg)
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 106: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/106.jpg)
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 107: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/107.jpg)
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 108: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/108.jpg)
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB
$ I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 109: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/109.jpg)
Runs Frequently
Runs Infrequently
Long LengthShort Length
var text = textViewtextStoragestring
1 KB1 MB1 GB
$128181128181128181128181128181128181128181
128181I
IVIII
II
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 110: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/110.jpg)
bullString bridging bullRanges bullText layout and rendering
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 111: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/111.jpg)
Rangesrdquo rdquo
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 112: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/112.jpg)
rdquo rdquo
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 113: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/113.jpg)
Visible Components 129318 127995
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 114: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/114.jpg)
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 115: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/115.jpg)
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 116: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/116.jpg)
Visible Components 129318 127995
Unicode Scalar Value 0x1F926 0x1F3FB 0x200D 0x2640 0xFE0F
Unicode Name
FACE PALM EMOJI MODIFIER FITZPATRICK TYPE-1-2
ZERO WIDTH JOINER FEMALE SIGN VARIATION
SELECTOR-16
UTF-16 0xD83E 0xDD26 0xD83C 0xDFFB 0x200D 0x2640 0xFE0F
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 117: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/117.jpg)
Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 118: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/118.jpg)
ldquoWhat a 127881128169rdquo
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 119: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/119.jpg)
ldquoWhat a 127881128169rdquo
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 120: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/120.jpg)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 121: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/121.jpg)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 122: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/122.jpg)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 let nsstring = string as NSString let nsrange = nsstringrangeOfString(128169) var attributedString = NSMutableAttributedString(string string) attributedStringaddAttribute(backgroundColor value color range nsrange)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 123: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/123.jpg)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 124: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/124.jpg)
String Ranges Example 1 Working with NSAttributedString
ldquoWhat a 127881128169rdquo
let string = What a 127881128169 var attributedString = NSMutableAttributedString(string string)let backgroundRange = stringrange(of ldquo128169) attributedStringaddAttribute(backgroundColor value color range NSRange(backgroundRange in string))
NEW
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 125: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/125.jpg)
Example 2 Working with NSRegularExpression
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 126: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/126.jpg)
String Ranges Working with NSRegularExpression
lthtmlgt ltbodygt ltdivgt
ltspangtHelloltspangt ltbgtSwiftltspangttestltspangtltbgt ltdivgt ltbodygt lthtmlgt
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 127: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/127.jpg)
String Ranges Working with NSRegularExpression
extension String func rangeFromNSRange(nsRange NSRange) -gt RangeltIndexgt guard nsRangelocation = NSNotFound else return nil let from16 = utf16startIndexadvanced(by nsRangelocation) let to16 = from16advanced(by nsRangelength) if let from = Index(from16 within self) let to = Index(to16 within self) return fromltto return nil
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 128: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/128.jpg)
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 129: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/129.jpg)
Improved String Ranges Working with NSRegularExpression
import Foundation
func findTags(in stringString) -gt [RangeltStringIndexgt] var found = [RangeltStringIndexgt]() let re = try NSRegularExpression(pattern lt([a-z][a-z0-9])gt) for match in rematches(in string range NSRange(stringstartIndexltstringendIndex in string)) foundappend(Range(matchrangeAt(1) in string)) return found
NEW
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 130: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/130.jpg)
bullString bridging bullRanges bullText layout and rendering
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 131: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/131.jpg)
Text is hard
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 132: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/132.jpg)
40 iOS localizations
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 133: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/133.jpg)
40 iOS localizations
35 macOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 134: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/134.jpg)
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 135: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/135.jpg)
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 136: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/136.jpg)
40 tvOS localizations
35 macOS localizations
40 iOS localizations
39 watchOS localizations
More than 300 other languages
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 137: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/137.jpg)
Font Leading
Tracking
Emoji
Truncation
Line Breaking
Unicode
BidirectionalCursor Positioning Dynamic Type Shaping Metrics
Hyphenation Widows Grapheme Cluster
Precomposed Characters
Script
RTL
LTR
Gamma
Tightening Orphans
Decomposed Characters
Spacing
Uncached
Orientation Glyph Bounds
Text MatrixEven-Odd
Kerning
Locale FontsFont Smoothing Margin
Non-Zero
FlippednessPattern Fill
Attributes
Writing Direction
Language
Screen Size Ligature FringingStroke
Glyph Dilation
Optical AlignmentLetterpress
EmAnti-Aliasing
Shadow
Line Height Clipping Legibility
Exclusion PathsLinear Blending
Glyph Bounds
Selection
Glyph Substitution
Encoding
AttachmentsLetterpress Bounding Boxes Baselines
Ascenders
DescendersAccessibility
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 138: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/138.jpg)
Example A Tale of Two Labels
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 139: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/139.jpg)
Millennium Park Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 140: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/140.jpg)
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 141: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/141.jpg)
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 142: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/142.jpg)
Millennium Park Loop
Tribune Tower Near North Side
Union Park West Loop
Rookery Building Loop
North Ave Beach Lincoln Park
Water Tower River North
Conservatory
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 143: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/143.jpg)
Robie House Hyde Park
Burnham Park Museum Campus
Union Station Loop
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 144: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/144.jpg)
长城 北北京
紫禁城 北北京
天安门广场 北北京
颐和园 北北京
天坛 北北京
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 145: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/145.jpg)
大同
虎跳峡 丽江
龙门石窟 洛洛阳
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 146: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/146.jpg)
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 147: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/147.jpg)
Runs Frequently
Runs Infrequently
Long LengthShort Length
I
IVIII
II
measure
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 148: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/148.jpg)
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 149: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/149.jpg)
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 150: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/150.jpg)
Postmortem Example A Tale of Two Labels
Initial conditions qualified for fast rendering
Input change forced rendering to slower path
App used older layout practices
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 151: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/151.jpg)
What You Can Do Higher-level strategies
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 152: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/152.jpg)
What You Can Do Higher-level strategies
Use standard label controls
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 153: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/153.jpg)
What You Can Do Higher-level strategies
Use standard label controls
3xfaster rendering with
NSTextField in macOS 1013
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 154: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/154.jpg)
What You Can Do Higher-level strategies
Use modern layout practices
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 155: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/155.jpg)
What You Can Do Lower-level tips
Set rendering attributes for attributed strings
let attributes [NSAttributedStringKey Any] = [ font UIFontsystemFont(ofSizesystemFontSize)
paragraphStyle NSParagraphStyledefault foregroundColor UIColordarkText]
let myString = NSAttributedString(string Hello attributes attributes)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 156: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/156.jpg)
What You Can Do Lower-level tips
Specify alignment and writing direction if known
Only do this if yoursquore absolutely sure your text doesnrsquot have mixed writing directions var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylebaseWritingDirection = leftToRight myParagraphStylealignment = left
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 157: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/157.jpg)
What You Can Do Lower-level tips
Use clipping line break mode for single line labels
Only do this if yoursquore sure your text doesnrsquot require wrapping var myParagraphStyle = NSMutableParagraphStyle() myParagraphStylelineBreakMode = byClipping
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 158: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/158.jpg)
SummaryFrequently Occurring
Infrequently Occurring
Large SizeSmall Size
$
cent
measure
measure
I
IVIII
II
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 159: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/159.jpg)
More Informationhttpsdeveloperapplecomwwdc17244
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 160: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/160.jpg)
Related Sessions
Understanding Swift Performance WWDC 2016
Whatrsquos New in Cocoa WWDC 2017
Whatrsquos New in Foundation WWDC 2017
Modernizing Grand Central Dispatch Usage WWDC 2017
Cocoa Development Tips WWDC 2017
Writing Energy Efficient Apps WWDC 2017
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 161: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/161.jpg)
Labs
Cocoa Lab Technology Lab B Fri 150PMndash320PM
![Page 162: Performance case studies...• Performance case studies • Session 244 App Frameworks Frequently Occurring Infrequently Occurring Small Size Large Size I III IV II Frequently Occurring](https://reader033.fdocuments.us/reader033/viewer/2022050405/5f826a85dc086a63d0345ffa/html5/thumbnails/162.jpg)