-
Notifications
You must be signed in to change notification settings - Fork 10.4k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[SR-3062] Ambiguous selector in Swift 3 for CoreBluetooth delegate methods #45652
Comments
cc @DougGregor |
Julien Coudsi (JIRA User), can I ask why you actually need the |
Comment by Julien Coudsi (JIRA) @belkadan It is to use a DelegateProxy with RxSwift, which needs to intercept delegates method by a selector to transform it to an observer. |
Comment by Julien Coudsi (JIRA) @belkadan @DougGregor Do you have an idea about it ? |
It looks like the 'NSError' parameter is imported as 'Error', and that's what's throwing off your workaround. optional public func peripheral(_ peripheral: CBPeripheral, didUpdateValueFor characteristic: CBCharacteristic, error: Error?) At the very least the error messages could certainly be better here (although I'm guessing the full version in the Log Navigator would have had useful notes). Being able to write the types inline is also a reasonable request, though that would have to go through the Swift Evolution Process and may be more work than is worth it for a relatively marginal feature. |
Comment by Julien Coudsi (JIRA) Well seen, it's an Error type. But I tried with "Error" and the problem is the same.
I don't understand by the compiler fails to match the good function, because the parameter types are different and specified in the selector... |
Oof. Turns out the method being optional is significant. This works for me: let selector = #selector(CBPeripheralDelegate.peripheral(_:didUpdateValueFor:error:) as ((CBPeripheralDelegate) -> (CBPeripheral, CBCharacteristic, Error?) -> Void)?) |
Comment by Julien Coudsi (JIRA) Perfect, it works for me, Thanks a lot 🙂 |
Since we expose optional methods as really being optional on protocol values, I think it's correct, just inconvenient (and poorly-diagnosed). someDelegate.peripheral?(device, didUpdateValueFor: characteristic, error: nil)
if let callback = someDelegate.peripheral(_:didUpdateValueFor:error:) as … { … } |
Comment by Julien Coudsi (JIRA) Thanks for your answer and for your explanations 🙂 |
Comment by Bob Godwin (JIRA) This problem is back in Swift 4 I am having this same issue in with Xcode 9.0.1 this is the method I am trying to wrap. WKNavigationDelegate.webView(_:decidePolicyFor:decisionHandler🙂 The naming clashes because there are 2 methods with same name. let sel = #selector((WKNavigationDelegate.webView(_:decidePolicyFor:decisionHandler🙂 as (WKNavigationDelegate) -> (WKWebView) -> (WKWebView, WKNavigationResponse, @escaping(WKNavigationResponsePolicy) -> Swift.Void ) -> Swift.Void )) Can you guys help or I should just give up on this? |
Well, the workaround above still works: wrap the function type in Optional to go with the requirement itself being optional. And we'd still like to improve it at some point. |
Comment by Bob Godwin (JIRA) @belkadan Sorry to disappoint you but it doesn't work![]( I have written this code in all forms and it kept on banging on same error. Tried the example above and it did not work) For goodness sake how can Apple be so careless to have this kind of naming conflicts. This is total negligence. Please go into this delegate WKNavigationDelegate and copy paste the how to create the `decisionHandleFor` related functions You can try it yourself with optional and everything you want but it doesn't work. Fix it Apple!!!! |
Works fine for me: import WebKit
func test() {
let sel = #selector(WKNavigationDelegate.webView(_:decidePolicyFor:decisionHandler:) as ((WKNavigationDelegate) -> (WKWebView, WKNavigationResponse, @escaping(WKNavigationResponsePolicy) -> Void) -> Void)?)
} Your example above does have an extra " |
@freak4pc @kennyevo It looks like getting the function as a value for an optional protocol method changed from being an optional function value to being a non-optional function that takes the instance and returns the instance function as an optional, so the position of the parentheses has to change. The following compiles for me (previous version shown commented out for comparison): static let decidePolicyNavigationResponse: Selector =
// #selector(WKNavigationDelegate.webView(_:decidePolicyFor:decisionHandler:) as ((WKNavigationDelegate) -> (WKWebView, WKNavigationResponse, @escaping (WKNavigationResponsePolicy) -> Void) -> Void)?)
#selector(WKNavigationDelegate.webView(_:decidePolicyFor:decisionHandler:) as (WKNavigationDelegate) -> ((WKWebView, WKNavigationResponse, @escaping (WKNavigationResponsePolicy) -> Void) -> Void)?)
static let decidePolicyNavigationAction: Selector =
// #selector(WKNavigationDelegate.webView(_:decidePolicyFor:decisionHandler:) as ((WKNavigationDelegate) -> (WKWebView, WKNavigationAction, @escaping(WKNavigationActionPolicy) -> Void) -> Void)?)
#selector(WKNavigationDelegate.webView(_:decidePolicyFor:decisionHandler:) as (WKNavigationDelegate) -> ((WKWebView, WKNavigationAction, @escaping(WKNavigationActionPolicy) -> Void) -> Void)?) |
Yes, this is mentioned in the change log. Unbound references to |
So would this have to live inside a compiler directive? This change doesn't work in Swift 5.6, for example. |
Yeah, you would have to branch out on |
There are a few open source projects that use this, we also have some internal stuff that uses it and we won't be moving everyone to Xcode 14 immediately, for obvious reasons :) Thanks you for the quick response 🙏 |
Sorry for the trouble! Apparently a selector is the only place where such a method ref did not cause a compiler crash. Was not expecting this to become a source compat issue, but since compelled selector disambiguation is a fairly narrow case, I believe the consistency in how we treat these refs across different expression contexts is for the best in the log term. |
In Swift 5.7, the type of an unbound reference to an |
I’m closing this because the disambiguation problem originally reported turned out to be a matter of spelling the types correctly rather than a missing feature. I’ve extracted the error quality bug that was found along the way into a fresh issue: #63834. |
Attachment: Download
Environment
Xcode 8.1, Swift 3
Additional Detail from JIRA
md5: 36322bb25de0649b7703eec4d6a684e0
Issue Description:
I need to declare a selector on
CBPeripheralDelegate
functions, for example :In Swift3, it is renamed to
peripheral(_: didUpdateValueFor:error)
, and it is same as thefunc peripheral(peripheral: CBPeripheral, didUpdateValueForDescriptor descriptor: CBDescriptor, error: NSError?)
So, when I try to define a selector like this :
It will cause a compile error: ambiguous use.
So I try to define with the parameters types :
I try also :
But it failed either.
The text was updated successfully, but these errors were encountered: