1

With the code below, I'm able to launch an HTTP request to my server and retrieve a JSON object thanks to Alamofire and Swiftyjson.

But I'm not able to pass the custom class JSON from Swiftyjson as an argument of my delegate method.

What should I do to fix this error?

Code line with error:

optional func didReceiveUserInfo(userInfo: JSON) //This the line I get the error

Error: Method cannot be a member of an @objc protocol because the type of parameter cannot be represented in in Objective-C

Here is the full code I'm using:

import UIKit
import Alamofire
import SwiftyJSON

@objc protocol UserModelDelegate {
    optional func didReceiveUserInfo(userInfo: JSON) //This is the line I get the error
}

class UserModel: NSObject, NSURLSessionDelegate {

    // Instantiate the delegate
    var delegate: UserModelDelegate?

    override init() {
        super.init()
    }

    func getUserInfo(token: String) {

        let url = "http://test.app/api/userInfo"

        let headers = [
            "Authorization":"Bearer \(token)",
            "Content-Type": "application/x-www-form-urlencoded"
        ]

        Alamofire.request(.GET, url, headers: headers).responseJSON { response in

            switch response.result {

                case .Success(let data):
                    let json = JSON(data)
                    self.delegate?.didReceiveUserInfo?(json) //This is where I pass the JSON custom class type as an argument

                case .Failure(let error):
                print("Request failed with error: \(error)")
            }
        }
    }
}
dan
  • 9,695
  • 1
  • 42
  • 40
sbkl
  • 2,231
  • 2
  • 22
  • 28

2 Answers2

0

I would probably make the protocol requirements not optional, in this case it will make total sense to do so as your delegate has a single requirement. The problem you're facing is because you need the JSON object type to be Objective-C compatible. You can do so by making the class inherit from a Objective-C class (like NSObject). Another thing that you should do is declaring the delegate property in UserModel a weak one, to avoid retain cycles.

Edit: An example of how to make a swift class compatible with Objective-C:

class JSON: NSObject {
//the code
}

Note: I previously stated that you needed to add an @objc attribute to the class. That's actually not necessary unless you want to make your class visible with other name in Objective-C.

For more info about Swift and Objective-C interoperability read here.

bitsoverflow
  • 556
  • 5
  • 15
  • Thank you for your answer. The thing is I would like to have a second requirement in case the request fails. Not sure to understand your answer about making the class inherit from a Objective-C class and adding the @objc attribute. How to do so? Sorry, I'm quite new to iOS development. – sbkl Apr 12 '16 at 03:20
  • @sbkl I added more info in my answer. – bitsoverflow Apr 12 '16 at 03:38
  • @sbkl also note that you can make your protocol requirement not optional, and use a default implementation in case the user doesn't want to implement it by using protocol extensions. More about it here: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-ID521 – bitsoverflow Apr 12 '16 at 03:43
  • I have checked the documentation but not sure how to implement it in my case. The class JSON is coming from the library swiftyjson. Should I modify this class to make it compliant with Objective-C? – sbkl Apr 12 '16 at 06:08
  • I'd rather make the protocol not objetive-c compatible and make a protocol extension to provide a default implementation of your requirement in case the request fails. This is an example of what I'm saying: http://stackoverflow.com/a/30744501/1763631 – bitsoverflow Apr 12 '16 at 14:02
  • Thanks a lot for your help @bitsoverflow. I managed to make it worked. I post the full code below as the solution – sbkl Apr 14 '16 at 05:41
0

Here is the code working:

import UIKit
import Alamofire
import SwiftyJSON

protocol UserModelDelegate {

    func didReceiveUserInfo(userInfo: JSON)

}

class UserModel: NSObject {

    // Instantiate the delegate
    var delegate: UserModelDelegate?

    override init() {

        super.init()

    }

    func getUserInfo(token: String) {

        let url = "http://test.app/api/userInfo"

        let headers = [
            "Authorization":"Bearer \(token)",
            "Content-Type": "application/x-www-form-urlencoded"
        ]


        Alamofire.request(.GET, url, headers: headers).responseJSON { response in
        switch response.result {
            case .Success(let data):

                if (data as? [String:AnyObject])!["error"] == nil {

                    let json = JSON(data)                

                    self.delegate?.didReceiveUserInfo(json)

                } else {

                    self.delegate?.didReceiveUserInfo(nil)

                }
            case .Failure(let error):
                print("Request failed with error: \(error)")
            }
        }
    }
}
sbkl
  • 2,231
  • 2
  • 22
  • 28
  • I recommend you to change your `var delegate: UserModelDelegate?` to `weak var delegate: UserModelDelegate?` to avoid retain cycles. – bitsoverflow Apr 14 '16 at 13:35