32

I converted my (macOS) project to Swift 3 in Xcode 8 and I get the following warnings with several delegate methods I implement in swift classes:

Instance method 'someMethod' nearly matches optional requirement of protocol 'protocolName'

I get this for several NSApplicationDelegate methods like applicationDidFinishLaunching and applicationDidBecomeActive:

enter image description here

But also for implementations of tableViewSelectionDidChange: enter image description here

enter image description here

I used code completion to insert the method signatures and also tried copying them from the SDK-headers to rule out typos. The warnings just don't disappear and the methods are never called.

What am I missing here?

Mindaugas
  • 1,707
  • 13
  • 20
codingFriend1
  • 6,487
  • 6
  • 45
  • 67
  • 1
    Simply change `NSNotification` to `Notification` for the first method, although your `tableViewSelectionDidChange` implementation compiles fine for me (warning free). Maybe try cleaning your build folder? – Hamish Sep 14 '16 at 17:07
  • @Hamish Switching to `Notification` had no effect (I adjusted the screenshot in the question accordingly). I also did a clean and deleted the Derived Data folder. – codingFriend1 Sep 14 '16 at 17:15
  • I got this error with code that was copy-and-pasted from Apple's own iOS development with Swift tutorial. In my case this info was what saved me: http://aplus.rs/2016/swift-3-migration-tip-instance-method-dot-dot-dot-nearly-matches-warning/ I.e., type in the func name manually and let intellisense provide the current correct parameters. – RenniePet Dec 03 '16 at 03:11

10 Answers10

29

We contacted Apple Developer Technical Support (DTS) with this issue. They replied that this is a bug in Xcode 8.

We submitted a bug report and hope for a quick update. (Apple Bug Report ID: 28315920).

If you experience a similar issue, please also file a bug report (referring to ours) so the Apple engineers see its not a single case.


Update for Xcode ≥ 8.1

The problem seems fixed now, at least for the delegate methods we are using in our project.

shim
  • 9,289
  • 12
  • 69
  • 108
codingFriend1
  • 6,487
  • 6
  • 45
  • 67
  • Done. Apple Bug Report ID: 28383728. Is it safe to ignore the warning? – dumbledad Sep 20 '16 at 09:53
  • @dumbledad No, the methods will never be called. – codingFriend1 Sep 20 '16 at 10:35
  • submitted 28921384 – pulp Oct 24 '16 at 19:56
  • Thanks. I have been looking at the issue . You saved me time, – Abdul Yasin Nov 18 '16 at 07:05
  • I re-approached converting my project to Swift 3 and I can confirm that the issue is solved in XCode 8.1 – codingFriend1 Dec 03 '16 at 11:22
  • 1
    My ID: 29691831. What a terrible error! And since September! I am having an issue with the XMLParserDelegate – Quintin Balsdon Dec 15 '16 at 22:22
  • 14
    I have updated to xCode 8.2 and I still have the issue :( – Quintin Balsdon Dec 18 '16 at 13:22
  • I am working on a Swift 3 project and had not seen this before till now. On Xcode 8.2.1. After going through my code, noticed that I only hit this issue when I had declared an extension with the same name as another class that implemented those delegate methods. – Inn0vative1 Feb 27 '17 at 06:12
  • I got it in xcode9. It showed up after moving an extension that added the delegate to a new file. The solution was to take the Delegate off the extension until xcode went through and was happy, then added it back and no more errors. – solenoid Jul 15 '17 at 17:40
  • I'm getting the same error in applicationDidBecomeActive in 8.3! When I click into the protocol in question the method is exactly right. So, definitely a serious bug. – SmileBot Jul 29 '17 at 23:27
  • 1
    Using Xcode 9.2 having same problem with application(_:open:options:) function... – Moosa Baloch Jan 15 '18 at 07:10
  • 1
    Using Xcode 10.1 still having this issue with `func animationController(forPresented presented: UIViewController, presenting: UIViewController, source: UIViewController) -> UIViewControllerAnimatedTransitioning?` – MikeG Jan 18 '19 at 18:31
  • If you still can't find out the solution, please see the answer below to make the method `public`. https://stackoverflow.com/a/54470346/749786 – Jake Lin Jun 20 '19 at 00:30
20

After hours of searching I found this - Swift 3 ObjC Optional Protocol Method Not Called in Subclass

You can workaround the bug by prefixing the objective-c declaration on the function

@objc(tableViewSettingsDidChange:notification:)
func tableViewSettingsDidChange(_ notification:Notification)
Community
  • 1
  • 1
MickCrozier
  • 312
  • 1
  • 8
  • 1
    The workaround works! The warning will stay, but it is now safe to ignore it as the method will get called. – pipacs Oct 04 '16 at 09:25
  • 1
    The workaround worked great for the URLSession:task:didCompleteWithError: method, whish seems to still remain problematic in Xcode 8.2.1. – Vitalii Jan 10 '17 at 11:50
  • I am trying to use this in xCode 8.3 and it no longer works for URLSession:task:didCompleteWithError, (I get error "method cannot be marked as @objc because the type of the 3rd parameter cannot be represented in Objective-C). I need to get this callback, any ideas? – RestingRobot May 31 '17 at 19:29
  • This is still happening in Xcode 10.1 and this workaround just helped our whole iOS team from going bananas. – nikolovski Nov 06 '18 at 13:22
18

One reason you might get this error has to do with method access modifiers. For example if you didn't define the function as public. So for methods on the CLLocationManagerDelegate case, changing:

func locationManager(_ manager: CLLocationManager,
                     didChangeAuthorization status: CLAuthorizationStatus)

to:

public func locationManager(_ manager: CLLocationManager,
                            didChangeAuthorization status: CLAuthorizationStatus)

(i.e. make the method public) gets rid of the warning and the method get called as expected. Note that autocomplete doesn't put the public access modifier on the method.

DCDC
  • 486
  • 5
  • 9
  • 1
    This should be the accepted answer. Most of these delegate methods are invoked from objc which does not have the same method access semantics, and requires `public` in order to "see" the swift method implementation. – ettore Apr 19 '19 at 17:24
  • 1
    Ran into the same issue and this fixed it. – Drew May 06 '19 at 18:36
  • That should be the accepted answer to help others to find out. – Jake Lin Jun 20 '19 at 00:29
9

for me the problem was custom Error class
Basically I had my own class with name Error and compiler was considering delegate method as a local method

I just changed name of my own class name and it worked. So, just confirm that you don't have any class name same in the function

Sultan Ali
  • 2,497
  • 28
  • 25
  • Thanks a lot!! You could also specify `Swift.Error` in the function, so that the compiler knows that it is the Swift Error and not your custom Error defined. That way don't have to rename your Error to something else. – user1046037 Nov 16 '20 at 03:31
  • Using Swift.Error I still get a warning. Changing to NSError, though, seems to have resolved the warning. – Victor Engel Jul 03 '21 at 19:46
  • just make sure you don't have any custom class with same name In the parameters of the function – Sultan Ali Jul 05 '21 at 07:43
8

Another cause of this warning when NSError is being bridged to Swift:

Given this Objective-C delegate method:

- (void)myService:(id<MYService>)myService didFailForSomeReason:(NSError *)error;

That automatically generates this Swift method:

public func myService(_ myService: MYService!, didFailForSomeReason error: Error!)

The warning was shown.

In my case the reason was that my class had it's own Error type so the signature was resolving to MyClass.Error rather than Swift.Error. The solution was to fully type the Error parameter by changing it to Swift.Error:

public func myService(_ myService: MYService!, didFailForSomeReason error: Swift.Error!)
Rory O'Bryan
  • 1,894
  • 14
  • 22
  • Wow this was exactly my problem – Rob C Jul 31 '19 at 03:22
  • Ok. I had an `Error` inside my object that was the delegate. So indeed the compiler was reporting this correctly since I needed `Swift.Error` to disambiguate. – SmileBot Jun 22 '22 at 19:54
3

For the record, I had the same problem when implementing WKWebView's didFailProvisionalNavigation delegate method. The solution was to add the @objc declaration and change the type of the last parameter from Error to NSError:

@objc(webView:didFailProvisionalNavigation:withError:)
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
    // handle error
}
pipacs
  • 1,049
  • 11
  • 25
1

Here's what fixed it for me.

I was getting the same warning in some code that I was sure that I typed into the editor initially and allowed it to autocomplete. I subsequently went back and re-visted the warning and tried to just type the same function over again right after my existing function. When I entered the function name over again, my function signature changed and the parms matched up exactly with what Xcode expected and the warning was suppressed.

So if you want to do a quick sanity check, do yourself a favor and try typing in the function one more time and see if the parm types change. That might be all you need.

ericdrum
  • 61
  • 4
0

Just to add clarification to this rather over complicated workaround: can anyone see why the below is not firing/working when the action is being taken?

extension AppDelegate: UNUserNotificationCenterDelegate {
    @objc(userNotificationCenter:didReceiveNotificationResponse:withCompletionHandler:)
    func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
        print("RESPONSE FROM NOTIFICATION!")

        switch response.actionIdentifier {
        case "reply":
            print("Reply action received!")
        case "ignore":
            print("Ignore action received!")
        default: print("Error - Unknown action received!")
            break
        }
    }
}
codingFriend1
  • 6,487
  • 6
  • 45
  • 67
  • @codingFriend1 Did you change anything to make it work or ...? Many thanks for clarifying :) – Mark Barrett Oct 06 '16 at 10:10
  • I just changed the formatting, so the code is displayed correctly. (Code must be indented to be formatted correctly). But in my testing, adding `@ objc` did not make it work. I am waiting for Apple to fix it... – codingFriend1 Oct 06 '16 at 17:11
  • gents - Is there any update on this? Now that official version of Xcode 8 is out? I still have the same warning and various delegate methods are not called. – Ahmed Khedr Oct 08 '16 at 17:49
0

This had me going around in circles. It was because I created my own Notification class. Once I changed this class name (don't refactor as it will change the objc Notification paramaters), all errors disappeared

Glenn Cooper
  • 157
  • 2
  • 13
-1

For xcode 8.1 >= and swift 3,

add @nonobjc at the beginning of method to silence this warning.

GuravS
  • 27
  • 1
  • 3
  • 1
    This does not provide an answer to the question. Once you have sufficient [reputation](http://stackoverflow.com/help/whats-reputation) you will be able to [comment on any post](http://stackoverflow.com/help/privileges/comment); instead, [provide answers that don't require clarification from the asker](http://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). - [From Review](/review/low-quality-posts/14657576) – Mayur Prajapati Dec 21 '16 at 07:07
  • 1
    This solution only silences the warning. The method itself still not called. So use this answer only when you don't actually want to call the method (have no idea in what situation such an "idle" method could be needed). – Vitalii Jan 10 '17 at 12:01