0

I'm using the parse iOS SDK with Swift and i'd like to factorize some code for Facebook and Twitter.

Currently there is 2 similar classes in the parse SDK : PFFacebookUtils and PFTwitterUtils and both expose almost the same methods.

I'd like to call the good class based on a string argument, eg : loginWith("facebook") and loginWith("twitter") as the process is almost the same.

Coming from javascript i've tried to call methods dynamically but didn't work.

Any idea how to achieve this the swift way ?

var networks: Dictionary<String, AnyObject> = [
    "facebook": PFFacebookUtils.self,
    "twitter": PFTwitterUtils.self
];

var test = networks[network].isLinkedWithUser(currentUser)

thanks !

jujule
  • 11,125
  • 3
  • 42
  • 63
  • You could do it functionally I guess? Instead of returning the class return the function. I know how to think about it but not how to code it in Swift which is why I didn't write an answer but give me a bit and I could find how to do it. – Fogmeister Nov 03 '14 at 14:45
  • i have many method calls following so i'd prefer to target the class dynamically. also i'm not a swift expert at all :) – jujule Nov 03 '14 at 14:54
  • See http://stackoverflow.com/questions/24030814/swift-language-nsclassfromstring – Rikkles Nov 03 '14 at 17:07

1 Answers1

2

You can call any class methods to AnyClass

//                               ↓
var networks: Dictionary<String, AnyClass> = [
    "facebook": PFFacebookUtils.self,
    "twitter": PFTwitterUtils.self
];

var flag = networks[network]?.isLinkedWithUser(user)
if flag == nil {
    // no such network
}
else if flag! {
    // linked
}
else {
    // not linked
}

If you don't know what ? means, see this document.

If you are sure networks[network] is exists:

var flag = networks[network]!.isLinkedWithUser(user)
if flag {
    // linked
}
else {
    // not linked
}

ADDED:

About unlinkUserInbackground method.

At first, I don't know the exact reason why the compiler cannot find this method, maybe a bug or maybe not. Following is a workaround I found.

unlinkUserInbackground method has 3 variations

class func unlinkUserInBackground(user: PFUser!) -> BFTask!
class func unlinkUserInBackground(user: PFUser!, block: PFBooleanResultBlock!)
class func unlinkUserInBackground(user: PFUser!, target: AnyObject!, selector: Selector)

I think, it's conflicted with each other.

If you import Bolts framework in YourProduct-Bridging-Header.h like this:

#import <ParseFacebookUtils/PFFacebookUtils.h>
#import <Bolts/Bolts.h>

then, you can call the first one.

 let cls:AnyClass = networks[network]!
 let task = cls.unlinkUserInBackground(user)

For the last 2, the workaround I found is... declaring an protocol like this.

@objc protocol SNSUtils {
    class func unlinkUserInBackground(user: PFUser!, block: PFBooleanResultBlock!)
    class func unlinkUserInBackground(user: PFUser!, target: AnyObject!, selector: Selector)
}

// ... 

    let cls:AnyClass = networks[network]!
    cls.unlinkUserInBackground(user, block: { (success, err) -> Void in
        println("sucess: \(success) err: \(err)")
    })

I know, it's odd, but it's actually working in my environment.

rintaro
  • 51,423
  • 14
  • 131
  • 139
  • Thanks man, that's awesome ! i still have a warning when using `var networkCls = networks[network]!;` . this gives : "Variable networkCls inffered to have type AnyClass which may be unexpected". Any way to say it can one of the two types only ? – jujule Nov 04 '14 at 09:21
  • You cannot constrain it can be only one of these two types. But, in your case, `var networkCls:AnyClass = networks[network]!` should be OK. – rintaro Nov 04 '14 at 09:51
  • thanks. also when using some other method of "networkCls".i get an error : "AnyClass does not have a member named 'unlinkUserInbackground'". is it a parameter issue ? worked fine with the real classes names – jujule Nov 04 '14 at 09:52
  • Added to the answer. Sorry for my bad English skills. I hope this helps. – rintaro Nov 04 '14 at 13:42