A small, flexible framework for expressing NSAttributedString
values structurally.
label.attributedText = [
"This is a string with ",
UIColor.blueColor().foregroundAttribute([
"blue ",
100.kernAttribute(
"kerned"
),
" text"
].join()),
" and ",
UIColor.redColor().foregroundAttribute([
NSAttributedString(string: "red", attributes: ["Custom": "Value"]),
" text"
].join()),
"."
].join().attributedString
Attributed defines the AttributedStringConvertible
protocol, which allows clients to create an NSAttributedString
value with the attributedString
property. String
and NSAttributedString
are extended to conform to this protocol.
The most important values in Attributed are attribute functions, which take an AttributedStringConvertible
value as a parameter, and return a second AttributedStringConvertible
value, with additional attributes applied. A basic attribute function can be created with the attribute(name:value:)
function:
let attributeFunction = attribute(name: "Foo", value: "Bar")
let attributedString = attributeFunction("Baz").attributedString
Multiple attributes can also be set at once:
let attributeFunction = attributes(values: [
"Foo": "Bar",
"Bar": "Foo"
])
let attributedString = attributeFunction("Baz").attributedString
The AttributeFunction
typealias
is provided to define this function type.
The core of Attributed's functionality is in the extensions added to support the standard attributes.
NSColor
and UIColor
are extended with these attribute functions:
foregroundAttribute
, which maps toNSForegroundColorAttributeName
.backgroundAttribute
, which maps toNSBackgroundColorAttributeName
.underlineAttribute
, which maps toNSUnderlineColorAttributeName
.strikethroughAttribute
, which maps toNSStrikethroughColorAttributeName
.
These additional framework types are extended with attribute functions:
NSCursor
, on OS X only:attributes
, which maps toNSCursorAttributeName
.NSFont
/UIFont
:attribute
, which maps toNSFontAttributeName
.NSTextAttachment
:attribute
, which maps toNSAttachmentAttributeName
.NSParagraphStyle
:attribute
, which maps toNSParagraphStyleAttributeName
.NSShadow
:attribute
, which maps toNSShadowAttributeName
.NSURL
:attribute
, which maps toNSLinkAttributeName
.NSUnderlineStyle
:attribute
, which maps toNSUnderlineStyleAttributeName
; andstrikethroughAttribute
, which maps toNSStrikethroughStyleAttributeName
.String
, on OS X only:toolTipAttribute
, which maps toNSToolTipAttributeName
.
Attributes with numeric values use the NSNumberConvertible
protocol. The framework provides implementations for these types:
NSNumber
Int
UInt
Int8
UInt8
Int16
UInt16
Int32
UInt32
Int64
UInt64
Float
Double
CGFloat
Types that conform to NSNumberConvertible
are extended with these functions:
baselineOffsetAttribute
, which maps toNSBaselineOffsetAttributeName
.expansionAttribute
, which maps toNSExpansionAttributeName
.kernAttribute
, which maps toNSKernAttributeName
.
To enforce valid values for the ligature attribute, the Ligature
type is declared as an enumeration, with the cases:
None
Default
All
(this case is only available on OS X)
The Ligature
enumeration is extended with the attribute
function, which maps to NSLigatureAttributeName
.
Attributed extends SequenceType
with join()
functions, which make flattening sequences of AttributedStringConvertible
and AttributeFunction
values possible.
let attributedString = [
UIColor.redColor().foregroundAttribute("Red"),
UIColor.greenColor().foregroundAttribute("Green")
].join().attributedString
let attributes = [
UIColor.redColor().foregroundAttribute,
UIColor.greenColor().backgroundAttribute
].join()
let attributedString = attributes("Complementary").attributedString
If you are writing an extension that composes with Attributed, it's best to work in terms of these two types. Here's an extension that applies Photoshop tracking values, which require knowledge of both the current font and the tracking value, and thus cannot be implemented as an AttributeFunction
-compatible extension of either type:
extension UIFont
{
public func photoshopTrackingAttributes(tracking: CGFloat) -> AttributeFunction
{
return [attribute, (pointSize * tracking / 1000).kernAttribute].join()
}
}
This is better than a function taking the tracking value and an attributed string convertible as two arguments and returning an AttributedStringConvertible
because it can be composed with other attribute functions:
let attributes = [
UIColor.redColor().foregroundAttribute,
font.photoshopTrackingAttributes(500)
].join()
let attributedString = attributes("Tracked Red").attributedString
Outer attributed values do not override inner values, so this code works as expected:
UIColor.greenColor().foregroundAttribute([
"There is some ",
UIColor.blueColor().foregroundAttribute(
"blue text "
),
"embedded in this green text."
].join())
Add:
github "natestedman/Attributed"
To your Cartfile
.