11

I am trying to create a protocol for JSON loading delegation, JSONLoaderDelegate. My other class, called JSONLoader, is supposed to dispatch events to its delegate (that implements the JSONLoaderDelegate protocol) like:

self?.delegate?.jsonLoaderdidEndWithError(self!, error: JSONLoaderError.LoadError)

The implementation of the JSONLoader is not that important (imho). However I seem to have problems to implement the protocol, this is the code:

@objc protocol JSONLoaderDelegate {

    optional func jsonLoaderdidBeginLoading(jsonLoader: JSONLoader)
    func jsonLoaderdidEndWithError(jsonLoader: JSONLoader, error: JSONLoader.JSONLoaderError)
    func jsonLoaderDidEndWithSuccess(jsonLoader: JSONLoader)

}

This looks pretty straightforward to me but I am getting an error:

method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C.

pointed to all three functions.

Obviously, if I remove the @objc attribute I cannot use the optional for the function. I would really like to keep jsonLoaderdidBeginLoading as optional tho. Any ideas / ways to solve this? Thank you!

4 Answers 4

8

I faced this problem as I had a class MyConnection that had no parent class. Like this.

public class MyConnection {
}

I can't put @objc before this, as I get a warning

Only classes that inherit from NSObject can be declared @objc

So I changed the class to be inherited from NSObject. Like this

public class MyConnection: NSObject {
}
Sign up to request clarification or add additional context in comments.

Comments

5

I had the same error. method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C.

I changed the syntax to the following in swift 2.0. It works fine now!

@objc protocol AppModelDelegate {
    optional func compititorList(com:[Competitor]!)
}

class Competitor:NSObject{
    var id:Int?
    var title:String?
}

Note: the Competitor class type changed to NSObject which cleared the delegate rule violation

Also in the case of NSJSON parsing. I changed to the following.

if (_httpStatusCode == 200) {
    let responseString = NSString(data: data!, encoding: NSUTF8StringEncoding)
    var error : NSError?
    print("responseString : \(responseString) ")

    var service_result:NSDictionary =  NSDictionary()
    do {
        let anyObj = try NSJSONSerialization.JSONObjectWithData(data!, options: []) as! [String:AnyObject]
        service_result = anyObj
    } catch let error as ErrorType {
        print("json error: \(error)")
    }
}

Comments

3

What the 3 methods have in common is the JSONLoader parameter, and that's what I think prevents you from bridging the protocol. In order to solve the problem you have to make it objc compatible.

4 Comments

Yes, your assumption is correct, or at least that's how I see it. However, how do I make it objc compatible? Do I just add "@objc" in front of "class JSONLoader"?
Add @objc to its declaration... and fix all things needed to make it compatible (no generics, for instance). In the end it might be the wrong approach.... just to have an optional func in a protocol. It's a trade off, and it's up to you which of the 2 options is better (objc compatible or no optional func)
Yeah, I see I cannot make an enum @objc compatible. I guess I will just get rid of that optional then. Oh well... Thanks for your help!
@Fygo You can get around the enum problem by declaring it in a C header file and bridging it to Swift or using the latest Xcode beta since Swift 1.2 supports @objc for basic enums: developer.apple.com/swift/blog/?id=22
2
JSONLoaderError.LoadError

Is this an enum type? You cannot convert Swift enums to Obj-C code. You'll need to use an int instead.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.