[swift-users] Instantiate Swift class from string

Matthew Davies daviesgeek at gmail.com
Thu Dec 10 17:53:06 CST 2015


You're right. I should be using a class instead…


*Matthew Davies*
Junior Developer, GeoStrategies <http://geostrategies.com>
Director of Photography, OffBlock Films <http://offblockfilms.com>
209-225-3246 <209-225.3246> | 209-202-3284 | daviesgeek at gmail.com |
daviesgeek.com
<http://facebook.com/daviesgeek>  <http://us.linkedin.com/in/daviesgeek>
<http://twitter.com/daviesgeek>  <http://daviesgeek.com/feed.xml>
<http://github.com/daviesgeek>


On Thu, Dec 10, 2015 at 3:47 PM, Daniel Dunbar <daniel_dunbar at apple.com>
wrote:

>
> On Dec 10, 2015, at 1:01 PM, Matthew Davies via swift-users <
> swift-users at swift.org> wrote:
>
> Yes I have the protoco
> ​l​
> , but the problem is that I would want to be able to call a method on the
> class that isn't necessarily defined in the protocol.
>
>
> You should only call methods that are defined in the protocol, and you
> should extend the protocol as necessary. You can always have instances
> conform to additional protocols and use conditional casts, if necessary.
>
> The value of this approach is that it is statically type safe, and users
> of your framework can easily tell what methods they need to implement to
> work with it.
>
>  - Daniel
>
>
> I.e., I would like to be able to do something like this
> ​:​
>
>
>
> ​---​
>
> protocol Controller {
>   init()
> }
>
> class MainController : Controller {
>
>   required init() {}
>
>   func index() -> String {
>     return "This is the index"
>   }
> }
>
> class Router {
>   func get(url: String, ctrl: Controller.Type, method: String) {
>     let inst = ctrl.init()
> *    // Run the method that is passed in here*
>   }
> }
>
> let router = Router()
> router.get("/", ctrl: MainController.self, method: "index")
> ​---​
>
> Does that make sense as to what I'm trying to accomplish? As I said, I'm
> open to suggestions. I'm relatively new to Swift's design patterns, so I
> may be thinking about this in completely the wrong way…
>
>
> On Thu, Dec 10, 2015 at 12:48 David Owens II <david at owensd.io> wrote:
>
>> You have the protocol conformance, why can’t you simply call the method
>> directly?
>>
>> On Dec 10, 2015, at 12:22 PM, Matthew Davies via swift-users <
>> swift-users at swift.org> wrote:
>>
>> I'm building a URL router in which I'd like to pass a controller and a
>> method. I don't want to instantiate all the controllers up front and pass
>> the methods in as closures, nor do I want old controller instances still
>> kept around. If there's a better way, I'm definitely open to any
>> suggestions. I'm still learning the "Swift" way to do things.
>>
>>
>> *Matthew Davies*
>> Junior Developer, GeoStrategies <http://geostrategies.com/>
>> Director of Photography, OffBlock Films <http://offblockfilms.com/>
>> 209-225-3246 <209-225.3246> | 209-202-3284 | daviesgeek at gmail.com |
>> daviesgeek.com
>> <http://facebook.com/daviesgeek>  <http://us.linkedin.com/in/daviesgeek>
>> <http://twitter.com/daviesgeek>  <http://daviesgeek.com/feed.xml>
>> <http://github.com/daviesgeek>
>>
>>
>> On Thu, Dec 10, 2015 at 10:47 AM, Dan Stenmark <
>> daniel.j.stenmark at gmail.com> wrote:
>>
>>> NSSelectorFromString() is still available in Swift, and you should be
>>> able to use the result of that in performSelector, though I’m hesitant to
>>> support this approach as it flies in the face of the safety Swift tries to
>>> enforce.  I’m curious about your use case here; are you trying to create
>>> some kind of dynamic proxy for a remote object ala NSXPCConnection?
>>>
>>> Dan
>>>
>>> On Dec 10, 2015, at 10:33 AM, Matthew Davies via swift-users <
>>> swift-users at swift.org> wrote:
>>>
>>> Ooh okay. I think that should work for my purposes. Thanks.
>>>
>>> Somewhat related to this, how would I then call a method dynamically on
>>> an instance of the class, after instantiating it?
>>>
>>> ---
>>> class Graph {
>>>   func call(method: String) {
>>>     // Something goes here
>>>   }
>>>
>>>   func redraw() -> String {
>>>     return "Redraws"
>>>   }
>>> }
>>>
>>> let inst = Graph()
>>> inst.call("redraw")
>>> ---
>>>
>>>
>>> *Matthew Davies*
>>> Junior Developer, GeoStrategies <http://geostrategies.com/>
>>> Director of Photography, OffBlock Films <http://offblockfilms.com/>
>>> 209-225-3246 <209-225.3246> | 209-202-3284 | daviesgeek at gmail.com |
>>> daviesgeek.com
>>> <http://facebook.com/daviesgeek>  <http://us.linkedin.com/in/daviesgeek>
>>>   <http://twitter.com/daviesgeek>  <http://daviesgeek.com/feed.xml>
>>> <http://github.com/daviesgeek>
>>>
>>>
>>> On Thu, Dec 10, 2015 at 10:18 AM, Daniel Dunbar <daniel_dunbar at apple.com
>>> > wrote:
>>>
>>>> Note that you can define a protocol which will allow your framework to
>>>> instantiate the type, and to call methods on instances of that type. If you
>>>> can structure your code in this fashion, it can be very elegant in that it
>>>> doesn't require factory functions and it is  type safe.
>>>>
>>>> For example:
>>>> --
>>>> struct GraphableDescription { }
>>>>
>>>> protocol Graphable {
>>>>     /// Construct a graphable item from a description.
>>>>     init(description: GraphableDescription)
>>>>
>>>>     func graph()
>>>> }
>>>>
>>>> // Example framework method.
>>>> func graphItem(description: GraphableDescription, graphable:
>>>> Graphable.Type) {
>>>>     // Instantiate the graphable.
>>>>     let item = graphable.init(description: description)
>>>>
>>>>     // Graph it.
>>>>     item.graph()
>>>> }
>>>>
>>>> // Example Graphable client.
>>>> struct Circle: Graphable {
>>>>     init(description: GraphableDescription) { }
>>>>
>>>>     func graph() { }
>>>> }
>>>>
>>>> // Example framework client.
>>>> func foo() {
>>>>     graphItem(GraphableDescription(), graphable: Circle.self)
>>>> }
>>>> --
>>>>
>>>>  - Daniel
>>>>
>>>> On Dec 10, 2015, at 9:59 AM, Matthew Davies via swift-users <
>>>> swift-users at swift.org> wrote:
>>>>
>>>> I don't really like the idea of a factory function, but unfortunately
>>>> that might be the only way to do it :( However, due to my specific use
>>>> case, I don't think a factory function will work. I'm working on a
>>>> framework that will need to both instantiate the class from a string (or
>>>> class type) *and* call methods dynamically on it. Which, I'm not sure
>>>> I can do in the build tools that are provided in the open source package.
>>>> Foundation hasn't been fully implemented and is missing a lot of the
>>>> methods that would allow this to work.
>>>>
>>>> @Jens thanks for that blog post. I'll have to make sure I check back to
>>>> see what his solution is for it.
>>>>
>>>>
>>>>
>>>>
>>>> *Matthew Davies*
>>>> Junior Developer, GeoStrategies <http://geostrategies.com/>
>>>> Director of Photography, OffBlock Films <http://offblockfilms.com/>
>>>> 209-225-3246 <209-225.3246> | 209-202-3284 | daviesgeek at gmail.com |
>>>> daviesgeek.com
>>>> <http://facebook.com/daviesgeek>
>>>> <http://us.linkedin.com/in/daviesgeek>  <http://twitter.com/daviesgeek>
>>>>   <http://daviesgeek.com/feed.xml>   <http://github.com/daviesgeek>
>>>>
>>>>
>>>> On Thu, Dec 10, 2015 at 9:30 AM, Jan Neumüller <swift-users at swift.org>
>>>> wrote:
>>>>
>>>>> Please no factory madness in Swift. This stuff is bad enough in Java -
>>>>> don’t infect Swift with it.
>>>>>
>>>>> Jan
>>>>>
>>>>> On 10.12.2015, at 18:23, Jens Alfke via swift-users <
>>>>> swift-users at swift.org> wrote:
>>>>>
>>>>>
>>>>> On Dec 10, 2015, at 7:26 AM, Harlan Haskins via swift-users <
>>>>> swift-users at swift.org> wrote:
>>>>>
>>>>> IIRC this isn’t possible because there’s no Runtime to query for
>>>>> classnames (it’s inherently unsafe anyway).
>>>>>
>>>>>
>>>>> It’s not unsafe if you specify a base class/protocol that the loaded
>>>>> class must conform to.
>>>>>
>>>>> You might want to look into a better way of doing that you’re trying
>>>>> to do.
>>>>>
>>>>>
>>>>> I disagree with “a better way” — “a workaround” is how I’d rephrase
>>>>> it. This kind of dynamism is often the best tool for the job, and a lot of
>>>>> Cocoa developers are frustrated by its absence in Swift. For example,
>>>>> there’s a series of blog posts from earlier this year by the highly
>>>>> respected Brent Simmons [NetNewsWire, MarsEdit, Glassboard, etc., currently
>>>>> at Omni]:
>>>>> http://inessential.com/swiftdiary
>>>>>
>>>>> http://inessential.com/2015/07/20/swift_diary_1_class_or_struct_from_str
>>>>>
>>>>> The workaround I’d suggest is a factory function that contains a
>>>>> switch statement that matches class names and returns newly initialized
>>>>> instances.
>>>>>
>>>>> —Jens
>>>>> _______________________________________________
>>>>> swift-users mailing list
>>>>> swift-users at swift.org
>>>>> https://lists.swift.org/mailman/listinfo/swift-users
>>>>>
>>>>>
>>>>>
>>>>> _______________________________________________
>>>>> swift-users mailing list
>>>>> swift-users at swift.org
>>>>> https://lists.swift.org/mailman/listinfo/swift-users
>>>>>
>>>>>
>>>>  _______________________________________________
>>>> swift-users mailing list
>>>> swift-users at swift.org
>>>> https://lists.swift.org/mailman/listinfo/swift-users
>>>>
>>>>
>>>>
>>>  _______________________________________________
>>> swift-users mailing list
>>> swift-users at swift.org
>>> https://lists.swift.org/mailman/listinfo/swift-users
>>>
>>>
>>>
>>  _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org
>> https://lists.swift.org/mailman/listinfo/swift-users
>>
>>
>>  _______________________________________________
> swift-users mailing list
> swift-users at swift.org
> https://lists.swift.org/mailman/listinfo/swift-users
>
>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-users/attachments/20151210/287f3fbc/attachment.html>


More information about the swift-users mailing list