implicit Objective-C entrypoint -[function I Wrote] is deprecated and will be removed in Swift 4; ???

so, i convert to swift 4. get the errors squared away, compile and then run my app.


the debugger sends me a grave warning that a function, that I wrote, with no ties to Apple code whatsoever... is being deprecated in swift 4.

should I be worried? What does Apple know about my project that I don't?


anyway, the significant bits of the warning are as follows:

*** /path to the class.swift:24:5: implicit Objective-C entrypoint -[appname.classname functionName:] is deprecated and will be removed in Swift 4; add explicit '@objc' to the declaration to emit the Objective-C entrypoint in Swift 4 and suppress this message


i don't want to supress the message, the whole point of getting on swift 4 is to be a good citizen. I just don't understand what it's trying to tell me. I "think" that it's saying there's significant changes coming to the Notification system (which is what that function is... a method that cooresponds to an addObserver call) but you can see, the feedback is somewhat de-illuminating.

Answered by QuinceyMorris in 242794022

>> then another function … got flagged with the same warning


There's no particular reason why there can't be multiple declarations that need fixing, and they can be scattered throughout your code.


I don't have enough information to be sure, but I'm guessing that "viewNeedsUi" is a method you're using to observe notifications, and you've registered the observation using the selector form (addObserver(_:selector:name:object:)), and this method is declared in a class that ultimately inherits from NSObject.


In Swift 3.1, the fact that the class was NSObject-derived meant that unannoted methods typically were assumed to be @objc. (This was not the assumption if the methods were marked private, but yours isn't private.) In that case, Swift actually compiled two methods, one with the Swift mangled name that could be called statically from other Swift code, for performance reasons, and another with the expected Obj-C name that is called dynamically through the Obj-C runtime. The second one just calls the first, but provides the Obj-C compatibility.


In Swift 4, without the @objc annotation, only the first method exists. That's why the error message told you to "add explicit '@objc' to the declaration to emit the Objective-C entrypoint in Swift 4". The Obj-C entrypoint is the second method, and you need it in order to be able to create a selector from its name.


>> in order to get IB to recognise classes, I've been forced to use "@objc" in the class declarations


Actually, that's the wrong solution to that problem. Look at the Identity inspector for the item you're trying to set to a custom class. Immediately under the class name field, there's a module name field, and below that there's an "Inherit From Target" checkbox. If your class is written in Swift, just make sure the checkbox is checked, and IB will use the correct name. For classes written in Obj-C, make sure the checkbox is unchecked. That means you don't have to provide an explicit Obj-C-compatible class name in your source code.


AFAICT, this @objc(name) issue is unrelated to the original issue.

>so, i convert to swift 4


From which previous version(s) Swift?

also: my app does not use Objective C. it was setup without any bridging headers.

Can you show us the declaration that's at class.swift line 24?


What the error message really means is:


You wrote an Obj-C compatible function which was assumed to be Obj-C compatible because of the context where you used it. In Swift 4, the compiler won't be making these assumptions any more, and so reliance on the assumption is deprecated in Swift 3.2.


All you should need to do is mark the function "@objc" to make the former assumption explicit. That will work in Swift 3.2 and 4, and you can move on.


The reason I'd be interested to see the declaration is that the error isn't clear what "implicit Objective-C entrypoint" means. It might just be jargon, or it might indicate something exceptional about this context. (However, since the error says to add "@objc", that's probably all you have to do.)

line 24:

func viewNeedsUi(_ note: NSNotification){



I did try adding @objc.

then another function in a completely different class, in a framework that I wrote, that the app depends on got flagged with the same warning.


I sat on that for a while and it occurred to me that in order to get IB to recognise classes, I've been forced to use "@objc" in the class declarations... for instance:

@objc(CNNode)
public class CNNode : CNObject, NSCopying


I thought maybe that was creating the issue. but the first thing I decided to check :if both classes so far effected, use "@objC" in the class declaration, turned out to not be true. No direct confirmation there.


It could still be the root cause, but I am at a loss on what to do here. IB doesn't recognise these classes if I delete it from the class declaration.

Accepted Answer

>> then another function … got flagged with the same warning


There's no particular reason why there can't be multiple declarations that need fixing, and they can be scattered throughout your code.


I don't have enough information to be sure, but I'm guessing that "viewNeedsUi" is a method you're using to observe notifications, and you've registered the observation using the selector form (addObserver(_:selector:name:object:)), and this method is declared in a class that ultimately inherits from NSObject.


In Swift 3.1, the fact that the class was NSObject-derived meant that unannoted methods typically were assumed to be @objc. (This was not the assumption if the methods were marked private, but yours isn't private.) In that case, Swift actually compiled two methods, one with the Swift mangled name that could be called statically from other Swift code, for performance reasons, and another with the expected Obj-C name that is called dynamically through the Obj-C runtime. The second one just calls the first, but provides the Obj-C compatibility.


In Swift 4, without the @objc annotation, only the first method exists. That's why the error message told you to "add explicit '@objc' to the declaration to emit the Objective-C entrypoint in Swift 4". The Obj-C entrypoint is the second method, and you need it in order to be able to create a selector from its name.


>> in order to get IB to recognise classes, I've been forced to use "@objc" in the class declarations


Actually, that's the wrong solution to that problem. Look at the Identity inspector for the item you're trying to set to a custom class. Immediately under the class name field, there's a module name field, and below that there's an "Inherit From Target" checkbox. If your class is written in Swift, just make sure the checkbox is checked, and IB will use the correct name. For classes written in Obj-C, make sure the checkbox is unchecked. That means you don't have to provide an explicit Obj-C-compatible class name in your source code.


AFAICT, this @objc(name) issue is unrelated to the original issue.

Thanks QuinceyMorris,

that seems to explain the whole thing.


here's the addObserver call:

NotificationCenter.default.addObserver( self,
selector: #selector(CNViewUIManager.viewNeedsUi),
name: NSNotification.Name(rawValue: "CNViewNeedsUI"),
object: nil)


the object does indeed inherit from NSObject (which it still has to... so long as I want to be able to instantiate it in IB, right?)

I hope Apple is headed somewhere with this change. I get that it's a kludge, but the change isn't much different.


as for the other thing... I have found that XCode does not always behave as expected. "inherit from target" does not always work as described. I cannot explain it, I don't understand it, I keep falling back on the advice I got from this forum in either swift 1 or 2... which works when other things don't. I will definetly try again.

it seems... anything referenced in the app with binding ALSO needs @objc

Yes, I believe you can only instantiate NSObject-derived objects in a NIB.


>> I hope Apple is headed somewhere with this change.


The motivation for this change in Swift 4 is in here:


github.com/apple/swift-evolution/blob/master/proposals/0160-objc-inference.md


Briefly, the old rules were too difficult to understand, so @objc must now be explicit everywhere, except in cases where it cannot be anything else (e.g. when overriding an @objc class or method, or when conforming to an @objc protocol). Unfortunately, it means adding @objc in a lot of cases where it seems "obvious".


>> anything referenced in the app with binding ALSO needs @objc


Yup. Any method called from a Cocoa class (including performed selectors, etc) goes through the Obj-C runtime dispatch, and so must be @objc.


>> XCode does not always behave as expected


Yes, and it wasn't always clear (or possibly even correct) in earlier versions of Xcode. But I haven't seen any difficulties with Xcode 9 (or even 8.3). What you were doing as a workaround isn't wrong, though. The only drawback is it puts your Obj-C class names back into a global namespace, rather than letting them be namespaced by the module they're in.

this kind of stuff is very difficutl to get from the swift org site, needles and haystacks.

I feel like I've learned something very important. Thanks!

implicit Objective-C entrypoint -[function I Wrote] is deprecated and will be removed in Swift 4; ???
 
 
Q