8:00 pm Sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Lorem Ipsum & the Dolor Sit Amets Wednesday, July 30, 1980 8:00 pm Sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et dolore magna aliquyam erat, sed diam voluptua. At vero eos et accusam et justo duo dolores et ea rebum.
.color(.red), .lineHeightMultiple(0.7), .alignment(.center), .tracking(.point(15)) ) let string = "Real Artists Ship".styled(with: style) label.attributedText = string Real Artists Ship ¶ NSAttributedString is hard to use easy
.color(.red), .lineHeightMultiple(0.7), .alignment(.center), .tracking(.adobe(1000)) ) let string = "Real Artists Ship".styled(with: style) label.attributedText = string ¶ NSAttributedString is hard to use easy Real Artists Ship
in a circus when Philip Astley hired jugglers to perform with his troupe in England. In 1793, juggling arrived to the circuses of the United States. proportional lowercase http://www.topendsports.com/juggling/history.htm proportional uppercase In 1768, jugglers first appeared as top acts in a circus when Philip Astley hired jugglers to perform with his troupe in England. In 1793, juggling arrived to the circuses of the United States.
in a circus when Philip Astley hired jugglers to perform with his troupe in England. In 1793, juggling arrived to the circuses of the United States. proportional lowercase http://www.topendsports.com/juggling/history.htm proportional uppercase In 1768, jugglers first appeared as top acts in a circus when Philip Astley hired jugglers to perform with his troupe in England. In 1793, juggling arrived to the circuses of the United States.
in a circus when Philip Astley hired jugglers to perform with his troupe in England. In 1793, juggling arrived to the circuses of the United States. proportional lowercase http://www.topendsports.com/juggling/history.htm proportional uppercase In 1768, jugglers first appeared as top acts in a circus when Philip Astley hired jugglers to perform with his troupe in England. In 1793, juggling arrived to the circuses of the United States. let originalDescriptor = myFont.fontDescriptor let featureSettings = [ [ UIFontFeatureTypeIdentifierKey: kNumberSpacingType, UIFontFeatureSelectorIdentifierKey: kMonospacedNumbersSelector, ], ] let attributes = [ UIFontDescriptorFeatureSettingsAttribute: featureSettings, ] let fontDescriptor = originalDescriptor.addingAttributes(attributes) let font = UIFont(descriptor: fontDescriptor, size: 0)
.color(.red), .lineHeightMultiple(0.7), .alignment(.center), .tracking(.adobe(1000)), .numberSpacing(.monospaced), .numberCase(.upper) ) let string = "Real Artists Ship".styled(with: style) label.attributedText = string ¶ NSAttributedString is hard to use easy Real Artists Ship
NSTextAttachment() attachment.image = attachment.bounds = CGRect(origin: .zero, size: .size) let imageString = NSAttributedString(attachment: attachment) let fullString = NSMutableAttributedString(string: " is awesome!") fullString.insert(imageString, at: 0) UNCAUGHT EXCEPTION (NSInvalidUnarchiveOperationException): *** -[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (UIImage) for key (NS.image); the class may be defined in source code or a library that is not linked rdar://30605012 is awesome!
it’s the result of years of research that have shown coupling between data and presentation to be ideal. @hyperspacemark Mark Adams ¶ Hard to style ranges of strings
"I went to Boston, and it was <strong>not</strong> too cold!" let strong = StringStyle( .font(myBoldFont) ) let style = StringStyle( .font(myNormalFont), .xmlRules([ .style("strong", strong), ])) let attributed = string.styled(with: style) Trivial I went to Boston, and it was not too cold!
"Je suis allé à Boston, et il <strong>ne</strong> faisait <strong>pas</strong> trop froid!" let strong = StringStyle( .font(myBoldFont) ) let style = StringStyle( .font(myNormalFont), .xmlRules([ .style("strong", strong), ])) let attributed = string.styled(with: style) Trivial Je suis allé à Boston, et il ne faisait pas trop froid!
// U+00A0: no-break space let test = "Swift\u{00A0}is\u{00A0}awesome!" XCTAssertEqual(test, "Swift is awesome!") } ("Swift is awesome!") is not equal to ("Swift is awesome!")
let string = "Swift<BON:noBreakSpace/>is<BON:noBreakSpace/>awesome!" let attributed = string.styled(with: .xmlRules([])) let test = attributed.bonMotDebugString XCTAssertEqual(test, "Swift is awesome!") } painless ("Swift<BON:noBreakSpace/>is<BON:noBreakSpace/>awesome!") is not equal to ("Swift is awesome!")
to use ¶ Hard to wrap images with text ¶ Hard to style ranges of strings ¶ Special characters are hard to read ¶ Dynamic Type API is limited rad painless Trivial Surprisingly easy Predictable-ish easy
color: BONColor? var underline: (NSUnderlineStyle, BONColor?)? var strikethrough: (NSUnderlineStyle, BONColor?)? var baselineOffset: CGFloat? var lineSpacing: CGFloat? var paragraphSpacingAfter: CGFloat? var alignment: NSTextAlignment? var firstLineHeadIndent: CGFloat? var lineHeightMultiple: CGFloat? // ✂ snip 40 lines var numberCase: NumberCase? var numberSpacing: NumberSpacing? var tracking: Tracking? } StringStyle (360 lines)
case font(BONFont) case backgroundColor(BONColor) case color(BONColor) case underline(NSUnderlineStyle, BONColor?) case strikethrough(NSUnderlineStyle, BONColor?) case baselineOffset(CGFloat) case alignment(NSTextAlignment) case tracking(Tracking) case lineSpacing(CGFloat) case paragraphSpacingAfter(CGFloat) case firstLineHeadIndent(CGFloat) case numberSpacing(NumberSpacing) case numberCase(NumberCase) case fractions(Fractions) // ✂ snip many lines } }