This is my research notebook. I'm an OSX / iOS indie developer. After 8 years of Objective-C I really enjoy Swift nowadays. Trying to publish all my research on Development, Swift & other technologies here.
Even though Swift stresses strong types, compile time safety, static dispatch it still offers a Reflection mechanism as part of the standard library. You may already have seen it in various blog posts or projects like here (Tuples), here (Midi Packets) or here (Core Data). Maybe you're interested in using in one of your projects, or you may want to better understand the problem domains on which reflection can be applied. This is an overview of the possibilities of the Swift Reflection API based a talk I held recently at the Macoun conference in Frankfurt, Germany.
1 API Overview
The best understanding of the topic can be achieved by having a look at the API to see what it offers us.
1.1 Mirrors
Swift's reflection capabilities are based around a struct called Mirror. You create a mirror for a particular subject and the mirror will then let you query it.
Before we do that, let's define a simple data structure that we can use as our subject.
import Foundation.NSURL
public class Store {
let storesToDisk: Bool = true
}
public class BookmarkStore: Store {
let itemCount: Int = 10
}
public struct Bookmark {
enum Group {
case Tech
case News
}
private let store = {
return BookmarkStore()
}()
let title: String?
let url: NSURL
let keywords: [String]
let group: Group
}
let aBookmark = Bookmark(title: "Appventure", url: NSURL(string: "appventure.me")!, keywords: ["Swift", "iOS", "OSX"], group: .Tech)
1.2 Creating a Mirror
The easiest way of creating a mirror is the reflecting initializer:
public init(reflecting subject: Any)
Lets use it with our aBookmarkstruct:
let aMirror = Mirror(reflecting: aBookmark)
print(aMirror)
// prints : Mirror for Bookmark
So this creates a Mirror for Bookmark. As you can see, the type of the subject is Any. This is the most general type in Swift. Anything the Swift sun is at least of type Any1. So this makes the mirror compatible with struct, class, enum, Tuple, Array, Dictionary, set, etc.
The Mirror struct contains several types to help you identify the information you'd like to query.
The first one is the DisplayStyleenum which tells you the type of the subject:
public enum DisplayStyle {
case Struct
case Class
case Enum
case Tuple
case Optional
case Collection
case Dictionary
case Set
}
Those are the supported types of the reflection API. As we saw earlier, reflection only requires an Any type, and there're many things in the Swift standard library that are of type Any but aren't listed in the DisplayStyle enum above. What happens when you try to reflect over one of those, say a closure?
let closure = { (a: Int) -> Int in return a * 2 }
let aMirror = Mirror(reflecting: closure)
In this case, you'd get a mirror, but the DisplayStyle would be nil 2
There's also a typealias for the child elements of a Mirror:
public typealias Child = (label: String?, value: Any)
So each child consists out of an optional label and a value of type Any. Why would the label be an Optional? If you think about it, it makes sense, not all of the structures that are supported by reflection have children with names. A struct has the property's name as the label, but a Collection only has indexes, not names. Tuples, also, may not have a name for their entries.
public enum AncestorRepresentation {
/// Generate a default mirror for all ancestor classes. This is the
/// default behavior.
case Generated
/// Use the nearest ancestor's implementation of `customMirror()` to
/// create a mirror for that ancestor.
case Customized(() -> Mirror)
/// Suppress the representation of all ancestor classes. The
/// resulting `Mirror`'s `superclassMirror()` is `nil`.
case Suppressed
}
This enum is used to define how superclasses of the reflected subject should be reflected. I.e. this is only used for subjects of type class. The default (as you can see) is that Swift generates an additional mirror for each superclass. However, if you need more flexibility here, you can use the AncestorRepresentation enum to define how superclasses are being mirrored. We will have a look at that further below.
1.4 How to use a Mirror
So we have our aMirror instance variable that reflects our aBookmark of type Bookmark subject. What do we do with it?
These are the available properties / methods on a Mirror:
let children: Children: The child elements of our subject
displayStyle: Mirror.DisplayStyle?: The display style of the subject
let subjectType: Any.Type : The type of the subject
func superclassMirror() -> Mirror?: The mirror of the subject's superclass
In the next step, we will analyze each of these.
1.4.1 displayStyle
This is easy. It will just return a case of the DisplayStyleenum. If you're trying to reflect over an unsupported type, you'll get an empty Optional back (as explained above).
This returns a AnyForwardCollection<Child> with all the children that the subject contains. Children are not limited to entries in an Array or Dictionary. All properties of a struct or class, for example, are also children returned by this property. The protocol AnyForwardCollection means that this is a collection type with indices that support forward traversal.
for case let (label?, value) in aMirror.children {
print (label, value)
}
//prints:
//: store main.BookmarkStore
//: title Optional("Appventure")
//: url appventure.me
//: keywords ["Swift", "iOS", "OSX"]
//: group Tech
However, the Swift documentation has the following to say:
This type may differ from the subject's dynamic type when self
is the superclassMirror() of another mirror.
1.4.4 SuperclassMirror
This is the mirror of the superclass of our subject. If the subject is not a class, this will be an empty Optional. If this is a class-based type, you'll get a new Mirror:
// try our struct
print(Mirror(reflecting: aBookmark).superclassMirror())
// prints: nil
// try a class
print(Mirror(reflecting: aBookmark.store).superclassMirror())
// prints: Optional(Mirror for Store)
2 Practical Example
2.1 Structs to Core Data
Imagine we're working at the newest, hot, tech startup: Books Bunny.
We offer an Artificial Intelligence with a browser plugin that automatically analyses all the sites that the user visits and automatically bookmarks the relevant urls.
It's 2016, Swift is already open source, so our server backend is obviously written in Swift. Since we have millions of site visits active in our system at a time, we'd like to use structs for the analysis part of each site that a user visits. However, if our AI decides that this is worthy of a bookmark, we'd like to use CoreData to store this type in a database.
Now, we don't want to write custom serialization to Core Data code whenever we introduce a new struct. Rather, we'd like to develop this in a way so that we can utilize it for all future structs we develop.
So, how do we do that?
2.2 A Protocol
Remember, we have a struct and want to automatically convert this to NSManagedObject (Core Data).
If we want to support different structs or even types, we can implement this as a protocol and then make sure our desired types conform to it. So which functionality should our imaginary protocol offer?
First, it should allow us to define the name of the Core Data Entity that we want to create
Second, it should have a way to tell it to convert itself to an NSManagedObject
Our protocol could look something like this:
protocol StructDecoder {
// The name of our Core Data Entity
static var EntityName: String { get }
// Return an NSManagedObject with our properties set
func toCoreData(context: NSManagedObjectContext) throws -> NSManagedObject
}
The toCoreData method uses the new Swift 2.0 exception handling to throw an error, if the conversion fails. There're several possible error cases, which are outlined in the ErrorTypeenum below:
enum SerializationError: ErrorType {
// We only support structs
case StructRequired
// The entity does not exist in the Core Data Model
case UnknownEntity(name: String)
// The provided type cannot be stored in core data
case UnsupportedSubType(label: String?)
}
We have three error cases that our conversion has to look out for. The first one is that we're trying to apply it to something that is not a struct. The second is that the entity we're trying to create does not exist in our Core Data Model. The third is that we're trying to write something into Core Data which can not be stored there (i.e. an enum).
Let's create a struct and add protocol conformance:
2.3 Bookmark struct
struct Bookmark {
let title: String
let url: NSURL
let pagerank: Int
let created: NSDate
}
Next, we'd like to implement the toCoreData method.
2.4 Protocol Extension
We could, of course, write this anew for each struct, but that's a lot of work. Structs do not support inheritance, so we can't use a base class. However, we can use a protocol extension to extend to all conforming structs:
As this extension is being applied to our conforming structs, this method will be called in the structs context. Thus, within the extension, self refers to the struct which we'd like to analyze.
So, the first step for us is to create an NSManagedObject into which we can then write the values from our Bookmark struct. How do we do that?
2.5 A Bit of Core Data
Core Data is a tad verbose, so in order to create an object, we need the following steps:
Get the name of the entity which we'd like to create (as a string)
Take the NSManagedObjectContext, and create an NSEntityDescription for our entity
Create an NSManagedObject with this information.
When we implement this, we have:
// Get the name of the Core Data Entity
let entityName = self.dynamicType.EntityName
// Create the Entity Description
// The entity may not exist, so we're using a 'guard let' to throw
// an error in case it does not exist in our core data model
guard let desc = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
else { throw UnknownEntity(name: entityName) }
// Create the NSManagedObject
let managedObject = NSManagedObject(entity: desc, insertIntoManagedObjectContext: context)
2.6 Implementing the Reflection
Next up, we'd like to use the Reflection API to read our bookmarks properties and write it into our NSManagedObject instance.
// Create a Mirror
let mirror = Mirror(reflecting: self)
// Make sure we're analyzing a struct
guard mirror.displayStyle == .Struct else { throw SerializationError.StructRequired }
We're making sure that this is indeed a struct by testing the displayStyle property.
So now we have a Mirror that allows us to read properties, and we have a NSManagedObject which we can set properties on. As the mirror offers a way to read all children, we can iterate over them and set the values. So let's do that.
for case let (label?, value) in mirror.children {
managedObject.setValue(value, forKey: label)
}
Awesome. However, if we try to compile this, it will fail. The reason is that setValueForKey requires an object of type AnyObject?, however our children property only returns a tuple of type (String?, Any) - i.e. our value is of type Any but we need an AnyObject. To solve this, we have to test the value for AnyObject conformance. This also means that we can throw an error if we receive a property with a type that does not conform to AnyObject (such as an enum, for example).
let mirror = Mirror(reflecting: self)
guard mirror.displayStyle == .Struct
else { throw SerializationError.StructRequired }
for case let (label?, anyValue) in mirror.children {
if let value = anyValue as? AnyObject {
managedObject.setValue(child, forKey: label)
} else {
throw SerializationError.UnsupportedSubType(label: label)
}
}
Now, our setValueForKey method will only be called if and only if the child is of type AnyObject.
Now, the only thing left to do is return our NSManagedObject. The complete code looks like this:
extension StructDecoder {
func toCoreData(context: NSManagedObjectContext) throws -> NSManagedObject {
let entityName = self.dynamicType.EntityName
// Create the Entity Description
guard let desc = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)
else { throw UnknownEntity(name: entityName) }
// Create the NSManagedObject
let managedObject = NSManagedObject(entity: desc, insertIntoManagedObjectContext: context)
// Create a Mirror
let mirror = Mirror(reflecting: self)
// Make sure we're analyzing a struct
guard mirror.displayStyle == .Struct else { throw SerializationError.StructRequired }
for case let (label?, anyValue) in mirror.children {
if let value = anyValue as? AnyObject {
managedObject.setValue(child, forKey: label)
} else {
throw SerializationError.UnsupportedSubType(label: label)
}
}
return managedObject
}
}
That's it. We're converting our struct to NSManagedObject.
3 Performance
So, how fast is this? Can this be used well in production? I did some testing:
Create 2000 NSManagedObjects
Native: 0.062 seconds
Reflection: 0.207 seconds
Native, here, means creating an NSManagedObject and setting the property values via setValueForKey. If you create a NSManagedObject subclass within Core Data and set the values directly on the properties (without the dynamic setValueForKey overhead) this is probably even faster.
So, as you can see, using reflection slows the whole process of creating NSManagedObjects down by about 3.5x. This is fine when you're using this for a limited amount of items, or when you don't have to care about speed. However, when you need to reflect over a huge amount of structs, this will probably kill your app's performance.
4 Custom Mirrors
As we already discussed earlier, there're other options creating a Mirror. This is useful, for example, if you need to customize just how much of your subject can be seen with a mirror. The Mirror Struct has additional initializers for this.
4.1 Collections
The first special init is tailor-made for collections:
public init<T, C : CollectionType where C.Generator.Element == Child>
(_ subject: T, children: C,
displayStyle: Mirror.DisplayStyle? = default,
ancestorRepresentation: Mirror.AncestorRepresentation = default)
Compared to the init(reflecting:) initializer above, this one allows us to define much more details about the reflection process.
It only works for collections
We can set the subject to be reflected and the children of the subject (the collection contents)
Interesting to note, here, is that you provide the children (i.e. properties) of your subject as a DictionaryLiteral which is a bit like a dictionary only that it can be used directly as function parameters. If we implement this for our Bookmark struct, it looks like this:
If we do another performance measurement now, there's even a slight improvement:
Create 2000 NSManagedObjects
Native: 0.062 seconds
Reflection: 0.207 seconds
Reflection: 0.203 seconds
But hardly worth the effort, as it defeats our initial purpose of reflecting over our struct's members.
5 Use Cases
So, where does this leave us? What are good use cases for this? Obviously, if you're working a lot of NSManagedObject's, this will considerably slow down your code base. Also if you only have one or two structs, it is easier, more performant, and less magical if you simply write a serialization technique yourself with the domain knowledge of your individual struct.
Rather, the reflection technique showcased here can be used if you have many, complicated structs, and you'd like to store some of those sometimes.
Examples would be:
Setting Favorites
Storing Bookmarks
Staring Items
Keeping the last selection
Storing the ast open item across restarts
Temporary storage of items during specific processes.
Apart from that, of course, you can also use reflection for other use cases:
Iterate over tuples
Analyze classes
Runtime analysis of object conformance
Generated detailed logging / debugging information automatically (i.e. for externally generated objects)
6 Discussion
The Reflection API exists primarily as a tool for the Playgrounds. Objects conforming to the reflection API can easily be displayed in a hierarchical way in the playgrounds sidebar. Thus, the performance is not optimal. Nevertheless, this has still interesting use cases outside of playgrounds as we explained in the Use Cases chapter.
7 More Information
The source documentation of the Reflection API is very detailed. I'd encourage everyone to have a look at that as well.
Also, there's a much more exhaustive implementation of the techniques showcased here in the CoreValue project on GitHub which allows you to easily encode and decode from / to Structs to CoreData.
{:description
"In this post I'll examine the Swift reflection API, see how fast it is, and will try to show use cases where it can be applied successfully.",
:keyword-tags (:swift :cocoa :ios),
:projects ({:project "Sarbatka", :link "/electronic-music.html"}),
:postlist
({:title "Blogstrapped.",
:url "/2011/12/01/blogstrapped/",
:tags "entrepeneurship blog",
:keyword-tags (:entrepeneurship :blog),
:date "Thu, 1 Dec 2011",
:keywords "entrepeneurship videro fear unknown stylemac",
:keyword-keywords
(:entrepeneurship :videro :fear :unknown :stylemac)}
{:title "Fast NSDictionary traversal in Objective-C",
:url "/2011/12/07/fast-nsdictionary-traversal-in-objective-c/",
:tags "objective-c ios cocoa",
:keyword-tags (:objective-c :ios :cocoa),
:date "Wed, 7 Dec 2011"}
{:title "How the iPad can improve focus",
:url "/2011/12/09/how-the-ipad-can-improve-focus/",
:tags "opinion",
:keyword-tags (:opinion),
:date "Fri, 9 Dec 2011"}
{:title "Use VIM as an Xcode alternative",
:url "/2013/01/29/use-vim-as-xcode-alternative-ios-mac-cocoa/",
:tags "cocoa objective-c ios",
:keyword-tags (:cocoa :objective-c :ios),
:date "Tue, 29 Jan 2013"}
{:title "Now Running Clojure",
:url "/2014/01/20/now-running-clojure/",
:tags "clojure blog",
:keyword-tags (:clojure :blog),
:date "Mon, 20 Jan 2014"}
{:title
"Debugging entitlement issues in Maps, iCloud, In-App, Keychain, or GameCenter",
:url
"/2014/01/21/debugging-entitlement-maps-icloud-gamecenter-issues/",
:tags "ios cocoa",
:keyword-tags (:ios :cocoa),
:date "Tue, 21 Jan 2014",
:keywords "ios cocoa entitlements",
:keyword-keywords (:ios :cocoa :entitlements)}
{:title
"Clojure/Enlive Static Site Generator that keeps your HTML intact",
:url
"/2014/01/22/clojure-enlive-static-site-generator-that-keeps-html-intact/",
:tags "blog clojure",
:keyword-tags (:blog :clojure),
:date "Wed, 22 Jan 2014",
:keywords "clojure static site generator jekyll html enlive",
:keyword-keywords
(:clojure :static :site :generator :jekyll :html :enlive)}
{:title "Finding a good URL Partitioning Scheme for PostgreSQL",
:url "/2014/01/24/finding-url-partitioning-scheme-postgres/",
:tags "postgresql clojure",
:keyword-tags (:postgresql :clojure),
:date "Fri, 24 Jan 2014",
:keywords "clojure postgresql partitioning scheme",
:keyword-keywords (:clojure :postgresql :partitioning :scheme)}
{:title "An Emacs Lisp tooling tutorial, writing a bulk mailer",
:url "/2014/01/29/emacs-lisp-tooling-tutorial-writing-bulk-mailer/",
:tags "emacs",
:keyword-tags (:emacs),
:date "Wed, 29 Jan 2014",
:keywords
"emacs lisp bulk mailer tutorial email vim vimscript evil",
:keyword-keywords
(:emacs :lisp :bulk :mailer :tutorial :email :vim :vimscript :evil)}
{:title
"Creating a Swift syntax extension: the Lisp 'cond' function",
:url "/2014/06/08/writing-simple-syntax-extensions-in-swift/",
:tags "swift ios cocoa",
:keyword-tags (:swift :ios :cocoa),
:date "Sun, 8 Jun 2014",
:keywords
"clojure lisp swift cond syntax macro extension cocoa ios feature",
:keyword-keywords
(:clojure
:lisp
:swift
:cond
:syntax
:macro
:extension
:cocoa
:ios
:feature)}
{:title "Swift optionals made simple",
:url "/2014/06/13/swift-optionals-made-simple/",
:tags "swift ios cocoa",
:keyword-tags (:swift :ios :cocoa),
:date "Fri, 13 Jun 2014",
:keywords
"lisp swift optional scala simple optionals switch chaining feature",
:keyword-keywords
(:lisp
:swift
:optional
:scala
:simple
:optionals
:switch
:chaining
:feature)}
{:title "Generic method overloading by protocol in Swift",
:url "/2015/06/17/swift-method-overloading-by-protocol/",
:tags "swift ios cocoa",
:keyword-tags (:swift :ios :cocoa),
:date "Wed, 17 Jun 2015",
:keywords
"swift optional simple overloading method protocol extensions generics feature",
:keyword-keywords
(:swift
:optional
:simple
:overloading
:method
:protocol
:extensions
:generics
:feature)}
{:title "Using try / catch in Swift with asynchronous closures",
:url "/2015/06/19/swift-try-catch-asynchronous-closures/",
:tags "swift ios",
:keyword-tags (:swift :ios),
:date "Fri, 19 Jun 2015",
:keywords "swift try catch errortype closure async result feature",
:keyword-keywords
(:swift :try :catch :errortype :closure :async :result :feature)}
{:title "Debugging advanced compilation errors in ClojureScript",
:url "/2015/07/02/debugging-clojurescript-advanced-compilation/",
:tags "clojure",
:keyword-tags (:clojure),
:date "Thu, 2 Jul 2015",
:keywords "debugging clojure clojurescript externs",
:keyword-keywords (:debugging :clojure :clojurescript :externs)}
{:title "Tuples in Swift, Advanced Usage and Best Practices",
:url "/2015/07/19/tuples-swift-advanced-usage-best-practices/",
:tags "swift",
:keyword-tags (:swift),
:date "Sun, 19 Jul 2015",
:keywords "swift tuples generics feature",
:keyword-keywords (:swift :tuples :generics :feature)}
{:title "Match Me if you can: Swift Pattern Matching in Detail.",
:url "/2015/08/20/swift-pattern-matching-in-detail/",
:tags "swift ios cocoa",
:keyword-tags (:swift :ios :cocoa),
:date "Thu, 20 Aug 2015",
:keywords
"feature lisp swift optional scala simple optionals switch chaining for pattern matching clojure haskell",
:keyword-keywords
(:feature
:lisp
:swift
:optional
:scala
:simple
:optionals
:switch
:chaining
:for
:pattern
:matching
:clojure
:haskell)}
{:title "Optional throw via try? in Swift 2 beta 6",
:url "/2015/08/25/optional-throw-swift/",
:tags "swift",
:keyword-tags (:swift),
:date "Tue, 25 Aug 2015",
:keywords
"swift error throw result either rethrow try syntax swift2",
:keyword-keywords
(:swift
:error
:throw
:result
:either
:rethrow
:try
:syntax
:swift2)}
{:title "Getting your iPhone 6s Chip Foundry from Swift",
:url "/2015/09/30/getting-iphone6s-foundry-from-swift/",
:tags "swift",
:keyword-tags (:swift),
:date "Wed, 30 Sep 2015",
:keywords
"swift iphone6s iphone tsmc samsung gestalt private api foundation",
:keyword-keywords
(:swift
:iphone6s
:iphone
:tsmc
:samsung
:gestalt
:private
:api
:foundation)}
{:title "Advanced & Practical Enum usage in Swift",
:url "/2015/10/17/advanced-practical-enum-examples/",
:tags "swift cocoa ios",
:keyword-tags (:swift :cocoa :ios),
:date "Sat, 17 Oct 2015",
:keywords
"feature swift enum algebraic caseclass union case switch pattern simple practical advanced example",
:keyword-keywords
(:feature
:swift
:enum
:algebraic
:caseclass
:union
:case
:switch
:pattern
:simple
:practical
:advanced
:example)}
{:title "The Swift Reflection API and what you can do with it",
:url "/2015/10/24/swift-reflection-api-what-you-can-do/",
:tags "swift cocoa ios",
:keyword-tags (:swift :cocoa :ios),
:date "Sat, 24 Oct 2015",
:keywords
"feature swift reflection struct class displayType mirror api reflecting any anyobject",
:keyword-keywords
(:feature
:swift
:reflection
:struct
:class
:displayType
:mirror
:api
:reflecting
:any
:anyobject)}
{:title "Reduce all the things",
:url "/2015/11/30/reduce-all-the-things/",
:tags "swift cocoa ios",
:keyword-tags (:swift :cocoa :ios),
:date "Mon, 30 Nov 2015",
:keywords
"feature swift reduce map filter group partition split interpose chunk functional programming flatMap",
:keyword-keywords
(:feature
:swift
:reduce
:map
:filter
:group
:partition
:split
:interpose
:chunk
:functional
:programming
:flatMap)}
{:title
"Swift Package Manager: Create and Use a X11 package on Linux",
:url "/2015/12/08/swift-ubuntu-x11-window-app/",
:tags "swift linux",
:keyword-tags (:swift :linux),
:date "Tue, 8 Dec 2015",
:keywords "linux x11 swift libx11 xserver xorg",
:keyword-keywords (:linux :x11 :swift :libx11 :xserver :xorg)}
{:title "Hirundo: Comfortably follow Swift Mailing Lists on OSX",
:url "/2016/02/02/hirundo-mac-app-swift-mailing-lists/",
:tags "swift cocoa ios",
:keyword-tags (:swift :cocoa :ios),
:date "Tue, 2 Feb 2016",
:keywords
"swift mac cocoa mailing list swift-dev swift-eveolution swift-users reading macosx",
:keyword-keywords
(:swift
:mac
:cocoa
:mailing
:list
:swift-dev
:swift-eveolution
:swift-users
:reading
:macosx)}
{:title "Three tips for concise Swift using the Guard statement",
:url "/2016/03/29/three-tips-for-clean-swift-code/",
:tags "swift cocoa ios",
:keyword-tags (:swift :cocoa :ios),
:date "Tue, 29 Mar 2016",
:keywords
"swift mac cocoa guard let enum pattern matching patterns",
:keyword-keywords
(:swift :mac :cocoa :guard :let :enum :pattern :matching :patterns)}
{:title "Using Git Hooks to prevent commiting test code",
:url "/2016/04/04/prevent-accidental-test-code-commits/",
:tags "git",
:keyword-tags (:git),
:date "Mon, 4 Apr 2016",
:keywords "git hook commit debug test code",
:keyword-keywords (:git :hook :commit :debug :test :code)}
{:title
"Force optionals in multi-unwrapped \"guard let\" or \"if let\"",
:url
"/2016/04/14/force-optionals-in-guard-or-let-optional-binding/",
:tags "swift cocoa ios",
:keyword-tags (:swift :cocoa :ios),
:date "Thu, 14 Apr 2016",
:keywords
"swift guard let unwrap bind binding unwrapped optional some none optionals",
:keyword-keywords
(:swift
:guard
:let
:unwrap
:bind
:binding
:unwrapped
:optional
:some
:none
:optionals)}
{:title "Raw value initializers for enums with associated types",
:url "/2016/04/23/associated-types-enum-raw-value-initializers/",
:tags "swift cocoa ios",
:keyword-tags (:swift :cocoa :ios),
:date "Sat, 23 Apr 2016",
:keywords
"swift optional enum raw value initializers associated type",
:keyword-keywords
(:swift
:optional
:enum
:raw
:value
:initializers
:associated
:type)}
{:title "SwiftWatch",
:url "/2016/04/28/swiftwatch/",
:tags "swift cocoa ios",
:keyword-tags (:swift :cocoa :ios),
:date "Thu, 28 Apr 2016",
:keywords
"swift hackernews reddit designernews lamernews socialnews swiftlang programming community post vote comment",
:keyword-keywords
(:swift
:hackernews
:reddit
:designernews
:lamernews
:socialnews
:swiftlang
:programming
:community
:post
:vote
:comment)}
{:title "Data in Swift 3 parsing a Doom WAD File",
:url "/2016/07/15/swift3-nsdata-data/",
:tags "swift cocoa ios",
:keyword-tags (:swift :cocoa :ios),
:date "Fri, 15 Jul 2016",
:keywords "swift doom wad lumps data nsdata swift3 binary bytes",
:keyword-keywords
(:swift :doom :wad :lumps :data :nsdata :swift3 :binary :bytes)}),
:tags
"any, anyobject, api, benedikt, c, class, clojure, clojurescript, cocoa, displayType, feature, html, ios, javascript, mac, mirror, objective-c, photodesk, reflecting, reflection, research, struct, stylemac, swift, terhechte",
:type :post,
:keywords
"feature swift reflection struct class displayType mirror api reflecting any anyobject",
:title "The Swift Reflection API and what you can do with it",
:author "Benedikt Terhechte",
:summary
"In this post I'll examine the Swift reflection API, see how fast it is, and will try to show use cases where it can be applied successfully.",
:feature-image
"/img-content/2015-10-24-swift-reflection-api-what-you-can-do-feature-image.jpg",
:categories
({:tag "blog", :url "/tags/blog/index.html", :count 3}
{:tag "clojure", :url "/tags/clojure/index.html", :count 4}
{:tag "cocoa", :url "/tags/cocoa/index.html", :count 16}
{:tag "emacs", :url "/tags/emacs/index.html", :count 1}
{:tag "entrepeneurship",
:url "/tags/entrepeneurship/index.html",
:count 1}
{:tag "git", :url "/tags/git/index.html", :count 1}
{:tag "ios", :url "/tags/ios/index.html", :count 17}
{:tag "linux", :url "/tags/linux/index.html", :count 1}
{:tag "objective-c", :url "/tags/objective-c/index.html", :count 2}
{:tag "opinion", :url "/tags/opinion/index.html", :count 1}
{:tag "postgresql", :url "/tags/postgresql/index.html", :count 1}
{:tag "swift", :url "/tags/swift/index.html", :count 18}),
:url "/2015/10/24/swift-reflection-api-what-you-can-do/",
:blog-index nil,
:watching nil,
:site-title "Appventure",
:keyword-keywords
(:feature
:swift
:reflection
:struct
:class
:displayType
:mirror
:api
:reflecting
:any
:anyobject)}
[{:keyword-tags (:swift :cocoa :ios),
:tags "swift cocoa ios",
:date "Sat, 24 Oct 2015",
:footnotes nil,
:meta
{:feature-image
"/img-content/2015-10-24-swift-reflection-api-what-you-can-do-feature-image.jpg",
:title "The Swift Reflection API and what you can do with it",
:keyword-tags (:swift :cocoa :ios),
:tags "swift cocoa ios",
:keyword-keywords
(:feature
:swift
:reflection
:struct
:class
:displayType
:mirror
:api
:reflecting
:any
:anyobject),
:keywords
"feature swift reflection struct class displayType mirror api reflecting any anyobject",
:summary
"In this post I'll examine the Swift reflection API, see how fast it is, and will try to show use cases where it can be applied successfully.",
:description
"In this post I'll examine the Swift reflection API, see how fast it is, and will try to show use cases where it can be applied successfully."},
:content
"<!-- #+feature-image: /img-content/2015-10-24-swift-reflection-api-what-you-can-do-feature-image.jpg -->\n\n<div id=\"table-of-contents\">\n<h2>Table of Contents</h2>\n<div id=\"text-table-of-contents\">\n<ul>\n<li><a href=\"#sec-1\">1. API Overview</a>\n<ul>\n<li><a href=\"#sec-1-1\">1.1. Mirrors</a></li>\n<li><a href=\"#sec-1-2\">1.2. Creating a Mirror</a></li>\n<li><a href=\"#sec-1-3\">1.3. What's in a Mirror</a></li>\n<li><a href=\"#sec-1-4\">1.4. How to use a Mirror</a>\n<ul>\n<li><a href=\"#sec-1-4-1\">1.4.1. displayStyle</a></li>\n<li><a href=\"#sec-1-4-2\">1.4.2. children</a></li>\n<li><a href=\"#sec-1-4-3\">1.4.3. SubjectType</a></li>\n<li><a href=\"#sec-1-4-4\">1.4.4. SuperclassMirror</a></li>\n</ul>\n</li>\n</ul>\n</li>\n<li><a href=\"#sec-2\">2. Practical Example</a>\n<ul>\n<li><a href=\"#sec-2-1\">2.1. Structs to Core Data</a></li>\n<li><a href=\"#sec-2-2\">2.2. A Protocol</a></li>\n<li><a href=\"#sec-2-3\">2.3. Bookmark struct</a></li>\n<li><a href=\"#sec-2-4\">2.4. Protocol Extension</a></li>\n<li><a href=\"#sec-2-5\">2.5. A Bit of Core Data</a></li>\n<li><a href=\"#sec-2-6\">2.6. Implementing the Reflection</a></li>\n</ul>\n</li>\n<li><a href=\"#sec-3\">3. Performance</a></li>\n<li><a href=\"#custommirrors\">4. Custom Mirrors</a>\n<ul>\n<li><a href=\"#sec-4-1\">4.1. Collections</a></li>\n<li><a href=\"#sec-4-2\">4.2. Classes or Structs</a></li>\n</ul>\n</li>\n<li><a href=\"#sec-5\">5. Use Cases</a></li>\n<li><a href=\"#sec-6\">6. Discussion</a></li>\n<li><a href=\"#sec-7\">7. More Information</a></li>\n</ul>\n</div>\n</div>\n<h6><a href=\"http://swift.gg/2015/11/23/swift-reflection-api-what-you-can-do/\">This post is also available in <b>🇨🇳Chinese</b></a><span> Thanks to </span><a href=\"http://swift.gg/tags/APPVENTURE/\">SwiftGG</a></h6>\n\n<p>\nEven though Swift stresses strong types, compile time safety, static dispatch it still offers a Reflection mechanism as part of the standard library. You may already have seen it in various blog posts or projects like <a href=\"http://design.featherless.software/enumerating-tuple-values-swift/?utm_campaign=Swift%252BSandbox&utm_medium=email&utm_source=Swift_Sandbox_12\">here (Tuples)</a>, <a href=\"http://design.featherless.software/enumerate-messages-midipacket-swift-reflection/\">here (Midi Packets)</a> or <a href=\"https://github.com/terhechte/corevalue\">here (Core Data).</a> Maybe you're interested in using in one of your projects, or you may want to better understand the problem domains on which reflection can be applied. This is an overview of the possibilities of the Swift Reflection API based a talk I held recently at the <a href=\"http://www.macoun.de\">Macoun conference</a> in Frankfurt, Germany.\n</p>\n\n<div id=\"outline-container-sec-1\" class=\"outline-2\">\n<h2 id=\"sec-1\"><span class=\"section-number-2\">1</span> API Overview</h2>\n<div class=\"outline-text-2\" id=\"text-1\">\n<p>\nThe best understanding of the topic can be achieved by having a look at the API to see what it offers us.\n</p>\n</div>\n\n<div id=\"outline-container-sec-1-1\" class=\"outline-3\">\n<h3 id=\"sec-1-1\"><span class=\"section-number-3\">1.1</span> Mirrors</h3>\n<div class=\"outline-text-3\" id=\"text-1-1\">\n<p>\nSwift's reflection capabilities are based around a <code>struct</code> called <b>Mirror</b>. You create a mirror for a particular <code>subject</code> and the mirror will then let you query it.\n</p>\n\n<p>\nBefore we do that, let's define a simple data structure that we can use as our subject.\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">import Foundation.NSURL\n\npublic class Store {\n let storesToDisk: Bool = true\n}\npublic class BookmarkStore: Store {\n let itemCount: Int = 10\n}\npublic struct Bookmark {\n enum Group {\n case Tech\n case News\n }\n private let store = {\n return BookmarkStore()\n }()\n let title: String?\n let url: NSURL\n let keywords: [String]\n let group: Group\n}\n\nlet aBookmark = Bookmark(title: \"Appventure\", url: NSURL(string: \"appventure.me\")!, keywords: [\"Swift\", \"iOS\", \"OSX\"], group: .Tech)\n</pre>\n</div>\n</div>\n</div>\n\n<div id=\"outline-container-sec-1-2\" class=\"outline-3\">\n<h3 id=\"sec-1-2\"><span class=\"section-number-3\">1.2</span> Creating a Mirror</h3>\n<div class=\"outline-text-3\" id=\"text-1-2\">\n<p>\nThe easiest way of creating a mirror is the <code>reflecting</code> initializer:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">public init(reflecting subject: Any)\n</pre>\n</div>\n\n<p>\nLets use it with our <code>aBookmark</code> <code>struct</code>:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">let aMirror = Mirror(reflecting: aBookmark)\nprint(aMirror)\n// prints : Mirror for Bookmark\n</pre>\n</div>\n\n<p>\nSo this creates a <code>Mirror for Bookmark</code>. As you can see, the type of the subject is <code>Any</code>. This is the most general type in Swift. Anything the Swift sun is at least of type <code>Any</code> <sup><a id=\"fnr.1\" name=\"fnr.1\" class=\"footref\" href=\"#fn.1\">1</a></sup>. So this makes the mirror compatible with <code>struct</code>, <code>class</code>, <code>enum</code>, <code>Tuple</code>, <code>Array</code>, <code>Dictionary</code>, <code>set</code>, etc.\n</p>\n\n<p>\nThere are three additional initializers in the Mirror struct, however those are mostly used for circumstances where you'd want to provide your own, custom mirror. We <a href=\"#custommirrors\">will explain those additional initializers below when we discuss custom mirrors</a>.\n</p>\n</div>\n</div>\n\n<div id=\"outline-container-sec-1-3\" class=\"outline-3\">\n<h3 id=\"sec-1-3\"><span class=\"section-number-3\">1.3</span> What's in a Mirror</h3>\n<div class=\"outline-text-3\" id=\"text-1-3\">\n<p>\nThe <code>Mirror struct</code> contains several <code>types</code> to help you identify the information you'd like to query.\n</p>\n\n<p>\nThe first one is the <code>DisplayStyle</code> <code>enum</code> which tells you the type of the subject:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">public enum DisplayStyle {\n case Struct\n case Class\n case Enum\n case Tuple\n case Optional\n case Collection\n case Dictionary\n case Set\n}\n</pre>\n</div>\n\n<p>\nThose are the supported types of the reflection API. As we saw earlier, reflection only requires an <code>Any</code> type, and there're many things in the Swift standard library that are of type <code>Any</code> but aren't listed in the <code>DisplayStyle</code> enum above. What happens when you try to reflect over one of those, say a closure?\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">let closure = { (a: Int) -> Int in return a * 2 }\nlet aMirror = Mirror(reflecting: closure)\n</pre>\n</div>\n\n<p>\nIn this case, you'd get a mirror, but the <code>DisplayStyle</code> would be nil <sup><a id=\"fnr.2\" name=\"fnr.2\" class=\"footref\" href=\"#fn.2\">2</a></sup>\n</p>\n\n<p>\nThere's also a <code>typealias</code> for the child elements of a <code>Mirror</code>:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">public typealias Child = (label: String?, value: Any)\n</pre>\n</div>\n\n<p>\nSo each child consists out of an optional <b>label</b> and a <b>value</b> of type <code>Any</code>. Why would the label be an <code>Optional</code>? If you think about it, it makes sense, not all of the structures that are supported by reflection have children with names. A <code>struct</code> has the property's name as the label, but a Collection only has indexes, not names. Tuples, also, may not have a name for their entries.\n</p>\n\n<p>\nNext up is the <code>AncestorRepresentation</code> <code>enum</code> <sup><a id=\"fnr.3\" name=\"fnr.3\" class=\"footref\" href=\"#fn.3\">3</a></sup>:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">public enum AncestorRepresentation {\n /// Generate a default mirror for all ancestor classes. This is the\n /// default behavior.\n case Generated\n /// Use the nearest ancestor's implementation of `customMirror()` to\n /// create a mirror for that ancestor. \n case Customized(() -> Mirror)\n /// Suppress the representation of all ancestor classes. The\n /// resulting `Mirror`'s `superclassMirror()` is `nil`.\n case Suppressed\n}\n</pre>\n</div>\n\n<p>\nThis <code>enum</code> is used to define how superclasses of the reflected subject should be reflected. I.e. this is only used for subjects of type <code>class</code>. The default (as you can see) is that Swift generates an additional mirror for each superclass. However, if you need more flexibility here, you can use the <code>AncestorRepresentation enum</code> to define how superclasses are being mirrored. <a href=\"#custommirrors\">We will have a look at that further below</a>. \n</p>\n</div>\n</div>\n\n<div id=\"outline-container-sec-1-4\" class=\"outline-3\">\n<h3 id=\"sec-1-4\"><span class=\"section-number-3\">1.4</span> How to use a Mirror</h3>\n<div class=\"outline-text-3\" id=\"text-1-4\">\n<p>\nSo we have our <code>aMirror</code> instance variable that reflects our <code>aBookmark</code> of type <code>Bookmark</code> subject. What do we do with it?\n</p>\n\n<p>\nThese are the available properties / methods on a <code>Mirror</code>:\n</p>\n\n<ul class=\"org-ul\">\n<li><code>let children: Children</code>: The child elements of our subject\n</li>\n<li><code>displayStyle: Mirror.DisplayStyle?</code>: The display style of the subject\n</li>\n<li><code>let subjectType: Any.Type</code> : The type of the subject\n</li>\n<li><code>func superclassMirror() -> Mirror?</code>: The mirror of the subject's superclass\n</li>\n</ul>\n\n<p>\nIn the next step, we will analyze each of these.\n</p>\n</div>\n\n<div id=\"outline-container-sec-1-4-1\" class=\"outline-4\">\n<h4 id=\"sec-1-4-1\"><span class=\"section-number-4\">1.4.1</span> displayStyle</h4>\n<div class=\"outline-text-4\" id=\"text-1-4-1\">\n<p>\nThis is easy. It will just return a case of the <code>DisplayStyle</code> <code>enum</code>. If you're trying to reflect over an unsupported type, you'll get an empty <code>Optional</code> back (as explained above).\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">print (aMirror.displayStyle)\n// prints: Optional(Swift.Mirror.DisplayStyle.Struct)\n</pre>\n</div>\n</div>\n</div>\n\n<div id=\"outline-container-sec-1-4-2\" class=\"outline-4\">\n<h4 id=\"sec-1-4-2\"><span class=\"section-number-4\">1.4.2</span> children</h4>\n<div class=\"outline-text-4\" id=\"text-1-4-2\">\n<p>\nThis returns a <code>AnyForwardCollection<Child></code> with all the children that the subject contains. Children are not limited to entries in an <code>Array</code> or <code>Dictionary</code>. All properties of a <code>struct</code> or <code>class</code>, for example, are also children returned by this property. The protocol <code>AnyForwardCollection</code> means that this is a collection type with indices that support forward traversal.\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">for case let (label?, value) in aMirror.children {\n print (label, value)\n}\n//prints:\n//: store main.BookmarkStore\n//: title Optional(\"Appventure\")\n//: url appventure.me\n//: keywords [\"Swift\", \"iOS\", \"OSX\"]\n//: group Tech\n</pre>\n</div>\n</div>\n</div>\n\n<div id=\"outline-container-sec-1-4-3\" class=\"outline-4\">\n<h4 id=\"sec-1-4-3\"><span class=\"section-number-4\">1.4.3</span> SubjectType</h4>\n<div class=\"outline-text-4\" id=\"text-1-4-3\">\n<p>\nThis is the type of the subject:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">print(aMirror.subjectType)\n//prints : Bookmark\nprint(Mirror(reflecting: 5).subjectType)\n//prints : Int\nprint(Mirror(reflecting: \"test\").subjectType)\n//prints : String\nprint(Mirror(reflecting: NSNull()).subjectType)\n//print : NSNull\n</pre>\n</div>\n\n<p>\nHowever, the Swift documentation has the following to say:\n</p>\n<blockquote>\n<p>\nThis type may differ from the subject's dynamic type when <code>self</code>\nis the <code>superclassMirror()</code> of another mirror.\n</p>\n</blockquote>\n</div>\n</div>\n\n<div id=\"outline-container-sec-1-4-4\" class=\"outline-4\">\n<h4 id=\"sec-1-4-4\"><span class=\"section-number-4\">1.4.4</span> SuperclassMirror</h4>\n<div class=\"outline-text-4\" id=\"text-1-4-4\">\n<p>\nThis is the mirror of the superclass of our subject. If the subject is not a class, this will be an empty <code>Optional</code>. If this is a class-based type, you'll get a new <code>Mirror</code>:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">// try our struct\nprint(Mirror(reflecting: aBookmark).superclassMirror())\n// prints: nil\n// try a class\nprint(Mirror(reflecting: aBookmark.store).superclassMirror())\n// prints: Optional(Mirror for Store)\n</pre>\n</div>\n</div>\n</div>\n</div>\n</div>\n\n<div id=\"outline-container-sec-2\" class=\"outline-2\">\n<h2 id=\"sec-2\"><span class=\"section-number-2\">2</span> Practical Example</h2>\n<div class=\"outline-text-2\" id=\"text-2\">\n</div><div id=\"outline-container-sec-2-1\" class=\"outline-3\">\n<h3 id=\"sec-2-1\"><span class=\"section-number-3\">2.1</span> Structs to Core Data</h3>\n<div class=\"outline-text-3\" id=\"text-2-1\">\n<p>\nImagine we're working at the newest, hot, tech startup: <b>Books Bunny</b>.\nWe offer an Artificial Intelligence with a browser plugin that automatically analyses all the sites that the user visits and automatically bookmarks the relevant urls. \n</p>\n\n<p>\nIt's 2016, Swift is already open source, so our server backend is obviously written in Swift. Since we have millions of site visits active in our system at a time, we'd like to use <code>structs</code> for the analysis part of each site that a user visits. However, if our AI decides that this is worthy of a bookmark, we'd like to use CoreData to store this type in a database. \n</p>\n\n<p>\nNow, we don't want to write custom serialization to Core Data code whenever we introduce a new <code>struct</code>. Rather, we'd like to develop this in a way so that we can utilize it for all future <code>structs</code> we develop.\n</p>\n\n<p>\nSo, how do we do that?\n</p>\n</div>\n</div>\n\n<div id=\"outline-container-sec-2-2\" class=\"outline-3\">\n<h3 id=\"sec-2-2\"><span class=\"section-number-3\">2.2</span> A Protocol</h3>\n<div class=\"outline-text-3\" id=\"text-2-2\">\n<p>\nRemember, we have a <code>struct</code> and want to automatically convert this to <code>NSManagedObject</code> (<b>Core Data</b>).\n</p>\n\n<p>\nIf we want to support different <code>structs</code> or even types, we can implement this as a protocol and then make sure our desired types conform to it. So which functionality should our imaginary protocol offer?\n</p>\n\n<ul class=\"org-ul\">\n<li>First, it should allow us to define the name of the <b>Core Data Entity</b> that we want to create\n</li>\n<li>Second, it should have a way to tell it to convert itself to an <code>NSManagedObject</code>\n</li>\n</ul>\n\n<p>\nOur <code>protocol</code> could look something like this:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">protocol StructDecoder {\n // The name of our Core Data Entity\n static var EntityName: String { get }\n // Return an NSManagedObject with our properties set\n func toCoreData(context: NSManagedObjectContext) throws -> NSManagedObject\n}\n</pre>\n</div>\n\n<p>\nThe <code>toCoreData</code> method uses the new Swift 2.0 exception handling to throw an error, if the conversion fails. There're several possible error cases, which are outlined in the <code>ErrorType</code> <code>enum</code> below:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">enum SerializationError: ErrorType {\n // We only support structs\n case StructRequired\n // The entity does not exist in the Core Data Model\n case UnknownEntity(name: String)\n // The provided type cannot be stored in core data\n case UnsupportedSubType(label: String?)\n}\n</pre>\n</div>\n\n<p>\nWe have three error cases that our conversion has to look out for. The first one is that we're trying to apply it to something that is not a <code>struct</code>. The second is that the <code>entity</code> we're trying to create does not exist in our Core Data Model. The third is that we're trying to write something into Core Data which can not be stored there (i.e. an <code>enum</code>).\n</p>\n\n<p>\nLet's create a struct and add protocol conformance:\n</p>\n</div>\n</div>\n\n<div id=\"outline-container-sec-2-3\" class=\"outline-3\">\n<h3 id=\"sec-2-3\"><span class=\"section-number-3\">2.3</span> Bookmark struct</h3>\n<div class=\"outline-text-3\" id=\"text-2-3\">\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">struct Bookmark {\n let title: String\n let url: NSURL\n let pagerank: Int\n let created: NSDate\n}\n</pre>\n</div>\n\n<p>\nNext, we'd like to implement the <code>toCoreData</code> method.\n</p>\n</div>\n</div>\n\n<div id=\"outline-container-sec-2-4\" class=\"outline-3\">\n<h3 id=\"sec-2-4\"><span class=\"section-number-3\">2.4</span> Protocol Extension</h3>\n<div class=\"outline-text-3\" id=\"text-2-4\">\n<p>\nWe could, of course, write this anew for each <code>struct</code>, but that's a lot of work. Structs do not support inheritance, so we can't use a base class. However, we can use a <code>protocol extension</code> to extend to all conforming <code>structs</code>:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">extension StructDecoder {\n func toCoreData(context: NSManagedObjectContext) throws -> NSManagedObject {\n }\n}\n</pre>\n</div>\n\n<p>\nAs this extension is being applied to our conforming <code>structs</code>, this method will be called in the structs context. Thus, within the extension, <code>self</code> refers to the <code>struct</code> which we'd like to analyze.\n</p>\n\n<p>\nSo, the first step for us is to create an <code>NSManagedObject</code> into which we can then write the values from our <code>Bookmark struct</code>. How do we do that? \n</p>\n</div>\n</div>\n\n<div id=\"outline-container-sec-2-5\" class=\"outline-3\">\n<h3 id=\"sec-2-5\"><span class=\"section-number-3\">2.5</span> A Bit of Core Data</h3>\n<div class=\"outline-text-3\" id=\"text-2-5\">\n<p>\nCore Data is a tad verbose, so in order to create an object, we need the following steps:\n</p>\n\n<ol class=\"org-ol\">\n<li>Get the name of the entity which we'd like to create (as a string)\n</li>\n<li>Take the <code>NSManagedObjectContext</code>, and create an <code>NSEntityDescription</code> for our entity\n</li>\n<li>Create an <code>NSManagedObject</code> with this information.\n</li>\n</ol>\n\n<p>\nWhen we implement this, we have:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">// Get the name of the Core Data Entity\nlet entityName = self.dynamicType.EntityName\n\n// Create the Entity Description\n// The entity may not exist, so we're using a 'guard let' to throw \n// an error in case it does not exist in our core data model\nguard let desc = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)\n else { throw UnknownEntity(name: entityName) }\n\n// Create the NSManagedObject\nlet managedObject = NSManagedObject(entity: desc, insertIntoManagedObjectContext: context)\n</pre>\n</div>\n</div>\n</div>\n\n<div id=\"outline-container-sec-2-6\" class=\"outline-3\">\n<h3 id=\"sec-2-6\"><span class=\"section-number-3\">2.6</span> Implementing the Reflection</h3>\n<div class=\"outline-text-3\" id=\"text-2-6\">\n<p>\nNext up, we'd like to use the Reflection API to read our bookmarks properties and write it into our <code>NSManagedObject</code> instance.\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">// Create a Mirror\nlet mirror = Mirror(reflecting: self)\n\n// Make sure we're analyzing a struct\nguard mirror.displayStyle == .Struct else { throw SerializationError.StructRequired }\n</pre>\n</div>\n\n<p>\nWe're making sure that this is indeed a <code>struct</code> by testing the <code>displayStyle</code> property.\n</p>\n\n<p>\nSo now we have a <code>Mirror</code> that allows us to read properties, and we have a <code>NSManagedObject</code> which we can set properties on. As the mirror offers a way to read all children, we can iterate over them and set the values. So let's do that.\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">for case let (label?, value) in mirror.children {\n managedObject.setValue(value, forKey: label)\n}\n</pre>\n</div>\n\n<p>\nAwesome. However, if we try to compile this, it will fail. The reason is that <code>setValueForKey</code> requires an object of type <code>AnyObject?</code>, however our <code>children</code> property only returns a <code>tuple</code> of type <code>(String?, Any)</code> - i.e. our value is of type <code>Any</code> but we need an <code>AnyObject</code>. To solve this, we have to test the value for <code>AnyObject</code> conformance. This also means that we can throw an error if we receive a property with a type that does not conform to <code>AnyObject</code> (such as an <code>enum</code>, for example).\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\" id=\"feature-image\">let mirror = Mirror(reflecting: self)\n\nguard mirror.displayStyle == .Struct \n else { throw SerializationError.StructRequired }\n\nfor case let (label?, anyValue) in mirror.children {\n if let value = anyValue as? AnyObject {\n\tmanagedObject.setValue(child, forKey: label)\n } else {\n\tthrow SerializationError.UnsupportedSubType(label: label)\n }\n}\n</pre>\n</div>\n\n<p>\nNow, our <code>setValueForKey</code> method will only be called if and only if the child is of type <code>AnyObject</code>.\n</p>\n\n<p>\nNow, the only thing left to do is return our <code>NSManagedObject</code>. The complete code looks like this:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">extension StructDecoder {\n func toCoreData(context: NSManagedObjectContext) throws -> NSManagedObject {\n\tlet entityName = self.dynamicType.EntityName\n\n\t// Create the Entity Description\n\tguard let desc = NSEntityDescription.entityForName(entityName, inManagedObjectContext: context)\n\t else { throw UnknownEntity(name: entityName) }\n\n\t// Create the NSManagedObject\n\tlet managedObject = NSManagedObject(entity: desc, insertIntoManagedObjectContext: context)\n\n\t// Create a Mirror\n\tlet mirror = Mirror(reflecting: self)\n\n\t// Make sure we're analyzing a struct\n\tguard mirror.displayStyle == .Struct else { throw SerializationError.StructRequired }\n\n\tfor case let (label?, anyValue) in mirror.children {\n\t if let value = anyValue as? AnyObject {\n\t\tmanagedObject.setValue(child, forKey: label)\n\t } else {\n\t\tthrow SerializationError.UnsupportedSubType(label: label)\n\t }\n\t}\n\n\treturn managedObject\n }\n}\n</pre>\n</div>\n\n<p>\nThat's it. We're converting our <code>struct</code> to <code>NSManagedObject</code>.\n</p>\n</div>\n</div>\n</div>\n\n<div id=\"outline-container-sec-3\" class=\"outline-2\">\n<h2 id=\"sec-3\"><span class=\"section-number-2\">3</span> Performance</h2>\n<div class=\"outline-text-2\" id=\"text-3\">\n<p>\nSo, how fast is this? Can this be used well in production? I did some testing:\n</p>\n\n <style type=\"text/css\">\n .linechart {\n border: 3px solid white;\n border-radius: 32px;\n font-family: Sans-Serif;\n color: white;\n font-weight: normal;\n padding: 4px;\n margin-bottom: 20px;\n }\n .redxx {\n background-color: red;\n }\n .greenxx {\n background-color: green;\n }\n .linechart > span {\n padding: 4px;\n }\n h3.ggx {\n font-family: Sans-Serif;\nfont-weight: normal;\n }\n .orangexx {\n background-color: orange;\n }\n </style>\n <div style=\"background-color: #ccc; padding: 20px; border-radius: 16px;\">\n\n <h3 class='ggx'>Create 2000 NSManagedObjects</h3>\n\n <div class=\"linechart greenxx\" style=\"width: 30%\">\n <span>Native: 0.062 seconds</span>\n </div>\n <div class=\"linechart redxx\">\n <span>Reflection: 0.207 seconds</span>\n </div>\n </div>\n\n<p>\nNative, here, means creating an <code>NSManagedObject</code> and setting the property values via <code>setValueForKey</code>. If you create a <code>NSManagedObject</code> subclass within Core Data and set the values directly on the properties (without the dynamic <code>setValueForKey</code> overhead) this is probably even faster.\n</p>\n\n<p>\nSo, as you can see, using reflection slows the whole process of creating <code>NSManagedObjects</code> down by about <b>3.5x</b>. This is fine when you're using this for a limited amount of items, or when you don't have to care about speed. However, when you need to reflect over a huge amount of <code>structs</code>, this will probably kill your app's performance.\n</p>\n</div>\n</div>\n\n<div id=\"outline-container-custommirrors\" class=\"outline-2\">\n<h2 id=\"custommirrors\"><a id=\"sec-4\" name=\"sec-4\"></a><span class=\"section-number-2\">4</span> Custom Mirrors</h2>\n<div class=\"outline-text-2\" id=\"text-custommirrors\">\n\n<p>\nAs we already discussed earlier, there're other options creating a Mirror. This is useful, for example, if you need to customize just how much of your <b>subject</b> can be seen with a mirror. The <code>Mirror Struct</code> has additional initializers for this. \n</p>\n</div>\n\n<div id=\"outline-container-sec-4-1\" class=\"outline-3\">\n<h3 id=\"sec-4-1\"><span class=\"section-number-3\">4.1</span> Collections</h3>\n<div class=\"outline-text-3\" id=\"text-4-1\">\n<p>\nThe first special <code>init</code> is tailor-made for collections:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">public init<T, C : CollectionType where C.Generator.Element == Child>\n (_ subject: T, children: C, \n displayStyle: Mirror.DisplayStyle? = default, \n ancestorRepresentation: Mirror.AncestorRepresentation = default)\n</pre>\n</div>\n\n<p>\nCompared to the <code>init(reflecting:)</code> initializer above, this one allows us to define much more details about the reflection process.\n</p>\n<ul class=\"org-ul\">\n<li>It only works for collections\n</li>\n<li>We can set the subject to be reflected <b>and</b> the children of the subject (the collection contents)\n</li>\n</ul>\n</div>\n</div>\n\n<div id=\"outline-container-sec-4-2\" class=\"outline-3\">\n<h3 id=\"sec-4-2\"><span class=\"section-number-3\">4.2</span> Classes or Structs</h3>\n<div class=\"outline-text-3\" id=\"text-4-2\">\n<p>\nThe second can be used for a <code>class</code> or a <code>struct</code>.\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">public init<T>(_ subject: T, \n children: DictionaryLiteral<String, Any>, \n displayStyle: Mirror.DisplayStyle? = default, \n ancestorRepresentation: Mirror.AncestorRepresentation = default)\n</pre>\n</div>\n\n<p>\nInteresting to note, here, is that you provide the children (i.e. properties) of your subject as a <code>DictionaryLiteral</code> which is a bit like a dictionary only that it can be used directly as function parameters. If we implement this for our <code>Bookmark struct</code>, it looks like this:\n</p>\n\n<div class=\"org-src-container\">\n\n<pre class=\"src src-swift\">extension Bookmark: CustomReflectable {\n func customMirror() -> Mirror {\n\tlet children = DictionaryLiteral<String, Any>(dictionaryLiteral: \n\t(\"title\", self.title), (\"pagerank\", self.pagerank), \n\t(\"url\", self.url), (\"created\", self.created), \n\t(\"keywords\", self.keywords), (\"group\", self.group))\n\n\treturn Mirror.init(Bookmark.self, children: children, \n\t displayStyle: Mirror.DisplayStyle.Struct, \n\t ancestorRepresentation:.Suppressed)\n }\n}\n</pre>\n</div>\n\n<p>\nIf we do another performance measurement now, there's even a slight improvement:\n</p>\n\n <div style=\"background-color: #ccc; padding: 20px; border-radius: 16px;\">\n\n <h3 class=\"ggx\">Create 2000 NSManagedObjects</h3>\n\n <div class=\"linechart greenxx\" style=\"width: 30%\">\n <span>Native: 0.062 seconds</span>\n </div>\n <div class=\"linechart redxx\">\n <span>Reflection: 0.207 seconds</span>\n </div>\n <div class=\"linechart orangexx\" style=\"width: 98%\">\n <span>Reflection: 0.203 seconds</span>\n </div>\n</div>\n\n<p>\nBut hardly worth the effort, as it defeats our initial purpose of reflecting over our <code>struct</code>'s members. \n</p>\n</div>\n</div>\n</div>\n\n<div id=\"outline-container-sec-5\" class=\"outline-2\">\n<h2 id=\"sec-5\"><span class=\"section-number-2\">5</span> Use Cases</h2>\n<div class=\"outline-text-2\" id=\"text-5\">\n<p>\nSo, where does this leave us? What are good use cases for this? Obviously, if you're working a lot of <code>NSManagedObject</code>'s, this will considerably slow down your code base. Also if you only have one or two <code>structs</code>, it is easier, more performant, and less magical if you simply write a serialization technique yourself with the domain knowledge of your individual <code>struct</code>.\n</p>\n\n<p>\nRather, the reflection technique showcased here can be used if you have many, complicated structs, and you'd like to store some of those sometimes. \n</p>\n\n<p>\nExamples would be:\n</p>\n\n<ul class=\"org-ul\">\n<li>Setting Favorites\n</li>\n<li>Storing Bookmarks \n</li>\n<li>Staring Items \n</li>\n<li>Keeping the last selection\n</li>\n<li>Storing the ast open item across restarts\n</li>\n<li>Temporary storage of items during specific processes.\n</li>\n</ul>\n\n<p>\nApart from that, of course, you can also use reflection for other use cases:\n</p>\n\n<ul class=\"org-ul\">\n<li>Iterate over tuples\n</li>\n<li>Analyze classes\n</li>\n<li>Runtime analysis of object conformance\n</li>\n<li>Generated detailed logging / debugging information automatically (i.e. for externally generated objects)\n</li>\n</ul>\n</div>\n</div>\n\n<div id=\"outline-container-sec-6\" class=\"outline-2\">\n<h2 id=\"sec-6\"><span class=\"section-number-2\">6</span> Discussion</h2>\n<div class=\"outline-text-2\" id=\"text-6\">\n<p>\nThe Reflection API exists primarily as a tool for the Playgrounds. Objects conforming to the reflection API can easily be displayed in a hierarchical way in the playgrounds sidebar. Thus, the performance is not optimal. Nevertheless, this has still interesting use cases outside of playgrounds as we explained in the <b>Use Cases</b> chapter.\n</p>\n</div>\n</div>\n\n<div id=\"outline-container-sec-7\" class=\"outline-2\">\n<h2 id=\"sec-7\"><span class=\"section-number-2\">7</span> More Information</h2>\n<div class=\"outline-text-2\" id=\"text-7\">\n<p>\nThe source documentation of the Reflection API is very detailed. I'd encourage everyone to have a look at that as well.\n</p>\n\n<p>\nAlso, there's a much more exhaustive implementation of the techniques showcased here in the <a href=\"http://github.com/terhechte/corevalue\">CoreValue</a> project on GitHub which allows you to easily encode and decode from / to Structs to CoreData.\n</p>\n</div>\n</div>\n<div id=\"footnotes\">\n<h2 class=\"footnotes\">Footnotes: </h2>\n<div id=\"text-footnotes\">\n\n<div class=\"footdef\"><sup><a id=\"fn.1\" name=\"fn.1\" class=\"footnum\" href=\"#fnr.1\">1</a></sup> <p>In particular, <code>Any</code> is an empty protocol and everything implicitly conforms to this protocol</p></div>\n\n<div class=\"footdef\"><sup><a id=\"fn.2\" name=\"fn.2\" class=\"footnum\" href=\"#fnr.2\">2</a></sup> <p>Or rather, an empty optional</p></div>\n\n<div class=\"footdef\"><sup><a id=\"fn.3\" name=\"fn.3\" class=\"footnum\" href=\"#fnr.3\">3</a></sup> <p>I've shortened the documentation a bit</p></div>\n\n\n</div>\n</div>",
:keywords
"feature swift reflection struct class displayType mirror api reflecting any anyobject",
:title "The Swift Reflection API and what you can do with it",
:filename "2015-10-24-swift-reflection-api-what-you-can-do.org",
:id 1478631696,
:url "/2015/10/24/swift-reflection-api-what-you-can-do/",
:javadate #inst "2015-10-23T22:00:00.000-00:00",
:keyword-keywords
(:feature
:swift
:reflection
:struct
:class
:displayType
:mirror
:api
:reflecting
:any
:anyobject)}]