{"id":11807,"date":"2015-07-23T11:13:15","date_gmt":"2015-07-23T15:13:15","guid":{"rendered":"http:\/\/mjtsai.com\/blog\/?p=11807"},"modified":"2016-02-12T14:13:29","modified_gmt":"2016-02-12T19:13:29","slug":"dynamic-swift","status":"publish","type":"post","link":"https:\/\/mjtsai.com\/blog\/2015\/07\/23\/dynamic-swift\/","title":{"rendered":"Dynamic Swift"},"content":{"rendered":"<p><a href=\"http:\/\/blog.shiftybit.net\/kvc-in-swift\/\">Lee Morgan<\/a>:<\/p>\r\n<blockquote cite=\"http:\/\/blog.shiftybit.net\/kvc-in-swift\/\">\r\n<p>We&rsquo;ll go ahead and extend our <code>KVC<\/code> protocol and add our default implementation.<\/p>\r\n<pre>extension KVC {\r\n    \r\n    func valueForKey(key : String) -&gt; Any? {\r\n    \r\n        let mirror = reflect(self)\r\n        \r\n        for index in 0 ..&lt; mirror.count {\r\n            let (childKey, childMirror) = mirror[index]\r\n            if childKey == key {\r\n                return childMirror.value\r\n            }\r\n        }\r\n        return nil\r\n    }\r\n}<\/pre>\r\n<\/blockquote>\r\n\r\n<p><a href=\"http:\/\/owensd.io\/2015\/07\/14\/key-value-coding-in-swift.html\">David Owens II<\/a> has a different implementation that also handles setting values:<\/p>\r\n<blockquote cite=\"http:\/\/owensd.io\/2015\/07\/14\/key-value-coding-in-swift.html\"><p>As you might be gathering, the basic premise is to use a backing store to maintain our values and type information. The implementation can then verify that the data coming in is correct.<\/p><\/blockquote>\r\n\r\n<p><a href=\"http:\/\/owensd.io\/2015\/07\/10\/swift-method-swizzling.html\">David Owens II<\/a>:<\/p>\r\n<blockquote cite=\"http:\/\/owensd.io\/2015\/07\/10\/swift-method-swizzling.html\">\r\n<p>But wait&#8230; if we can shadow the functions and replace them with our own implementations, then this means that method swizzling is back on the table!<\/p>\r\n<\/blockquote>\r\n<p>There are several caveats, though.<\/p>\r\n\r\n<p><a href=\"https:\/\/netguru.co\/blog\/reflection-swift\">Adrian Kashivskyy<\/a>:<\/p>\r\n<blockquote cite=\"https:\/\/netguru.co\/blog\/reflection-swift\"><p>Remember that reflection in Swift is currently read-only and there&rsquo;s no way to modify your program at runtime (with Objective-C-derived classes being an exception as you can still <code>class_addMethod()<\/code>&nbsp;in Swift).<\/p><\/blockquote>\r\n\r\n<p><a href=\"https:\/\/twitter.com\/brentsimmons\/status\/622970531575259137\">Brent Simmons<\/a> asks how to instantiate an arbitrary class at runtime.<\/p>\r\n<p><a href=\"https:\/\/twitter.com\/owensd\/status\/622973551570653184\">David Owens II<\/a>:<\/p>\r\n<blockquote cite=\"https:\/\/twitter.com\/owensd\/status\/622973551570653184\"><p>The same way as C++, an ugly switch statement!<\/p><\/blockquote>\r\n<p><a href=\"https:\/\/gist.github.com\/tjw\/4f3ea2be02e5877746aa#gistcomment-1496414\">Wil Shipley<\/a>:<\/p>\r\n<blockquote cite=\"https:\/\/gist.github.com\/tjw\/4f3ea2be02e5877746aa#gistcomment-1496414\"><p>On the latest Swift you have to add the word &ldquo;init&rdquo; to make this more explicit. Then it works. e.g:<\/p>\r\n<pre>let a:P = clsA.init(i:1)<\/pre><\/blockquote>\r\n\r\n<p><a href=\"http:\/\/inessential.com\/2015\/07\/20\/swift_diary_1_class_or_struct_from_str\">Brent Simmons<\/a>:<\/p>\r\n<blockquote cite=\"http:\/\/inessential.com\/2015\/07\/20\/swift_diary_1_class_or_struct_from_str\"><p>Jim takes this one step further: what if all you have is the class name as a string?<\/p><\/blockquote>\r\n<p>Alas, that&rsquo;s currently only possible using Objective-C classes. There is no <code>NSClassFromString()<\/code> for Swift. [Update (2015-07-23): Actually, there is. See the comments below.]<\/p>\r\n\r\n<p><a href=\"http:\/\/owensd.io\/2015\/07\/22\/dynamic-swift.html\">David Owens II<\/a>:<\/p>\r\n<blockquote cite=\"http:\/\/owensd.io\/2015\/07\/22\/dynamic-swift.html\"><p>Xcode 7 Beta 4 is out and it is a doozy! One of the changes is that <code>performSelector<\/code> is now available from Swift. Now, this isn&rsquo;t going to make your Swift types dynamic all of a sudden. However, what it does open the door for, is writing both your ObjC-style code and your Swift code all in the same language: Swift.<\/p><\/blockquote>\r\n\r\n<p><a href=\"http:\/\/inessential.com\/2015\/07\/22\/swift_diary_2_kvc\">Brent Simmons<\/a>:<\/p>\r\n<blockquote cite=\"http:\/\/inessential.com\/2015\/07\/22\/swift_diary_2_kvc\"><p>Here&rsquo;s the deal I&rsquo;m willing to make: to make my code more elegant (read: smaller, easier to maintain, reusable), I&rsquo;m willing to let it crash if I&rsquo;ve configured things incorrectly.<\/p>\r\n<p>[&#8230;]<\/p>\r\n<p>So my case is that Swift itself needs things like this. If not a clone of KVC, then something very much like it.<\/p><\/blockquote>\r\n\r\n<p><a href=\"http:\/\/martiancraft.com\/blog\/2015\/07\/objective-c-swift-core-data\/\">Rob Rhyne<\/a>:<\/p>\r\n<blockquote cite=\"http:\/\/martiancraft.com\/blog\/2015\/07\/objective-c-swift-core-data\/\">\r\n<p>When Apple announced the Swift programming language in 2014, there were questions about the future of frameworks that depended heavily on the dynamic nature of Objective-C. Frameworks such as Core Data marshall objects with type dependencies determined at runtime. The strict type checks required by the Swift compiler appeared in conflict with Core Data.<\/p>\r\n<p>[&#8230;]<\/p>\r\n<p>It turns out the answer to one question begat the solution to the other. By turning this class extension into a protocol and with a clever use of <code>typealias<\/code>, I resolved the insidious casting problem while maintaining type safety. Protocols to the rescue!<\/p>\r\n<\/blockquote>\r\n<p>In other words, there are ways to use Core Data from Swift in a type-safe way. But it would still be impossible to write Core Data itself in pure Swift.<\/p>","protected":false},"excerpt":{"rendered":"<p>Lee Morgan: We&rsquo;ll go ahead and extend our KVC protocol and add our default implementation. extension KVC { func valueForKey(key : String) -&gt; Any? { let mirror = reflect(self) for index in 0 ..&lt; mirror.count { let (childKey, childMirror) = mirror[index] if childKey == key { return childMirror.value } } return nil } } David [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"apple_news_api_created_at":"","apple_news_api_id":"","apple_news_api_modified_at":"","apple_news_api_revision":"","apple_news_api_share_url":"","apple_news_coverimage":0,"apple_news_coverimage_caption":"","apple_news_is_hidden":false,"apple_news_is_paid":false,"apple_news_is_preview":false,"apple_news_is_sponsored":false,"apple_news_maturity_rating":"","apple_news_metadata":"\"\"","apple_news_pullquote":"","apple_news_pullquote_position":"","apple_news_slug":"","apple_news_sections":"\"\"","apple_news_suppress_video_url":false,"apple_news_use_image_component":false,"footnotes":""},"categories":[4],"tags":[109,31,1245,46,30,966,54,901,943],"class_list":["post-11807","post","type-post","status-publish","format-standard","hentry","category-programming-category","tag-coredata","tag-ios","tag-key-value-coding-kvc","tag-languagedesign","tag-mac","tag-message-passing","tag-objective-c","tag-swift-programming-language","tag-swift-runtime"],"apple_news_notices":[],"_links":{"self":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/11807","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/comments?post=11807"}],"version-history":[{"count":4,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/11807\/revisions"}],"predecessor-version":[{"id":13524,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/posts\/11807\/revisions\/13524"}],"wp:attachment":[{"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/media?parent=11807"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/categories?post=11807"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mjtsai.com\/blog\/wp-json\/wp\/v2\/tags?post=11807"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}