Skip to content
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-9676] Default implementation for optional protocol functions not invoked #52119

Closed
swift-ci opened this issue Jan 16, 2019 · 1 comment
Closed
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior.

Comments

@swift-ci
Copy link
Collaborator

Previous ID SR-9676
Radar None
Original Reporter nickweaver (JIRA User)
Type Bug
Status Resolved
Resolution Duplicate
Additional Detail from JIRA
Votes 0
Component/s
Labels Bug
Assignee None
Priority Medium

md5: c948e1f6e6fec2b19196b6af4576171b

duplicates:

  • SR-492 Protocol extenstion methods aren't exposed to Objective-C

Issue Description:

The following code should reproduce the issue: When a protocol(MyProtocol in this case) inherits from a protocol(OptionalDelegate) containing optional methods(doTheOptionalThing) and an extension is providing a default implementation for the optional methods they are not invoked when conforming instance is assigned to a property (delegate pattern).

See especially comments 2. and 3. below, the line "I am doing the OPTIONAL thing!" is not showing up as it should. It seems the optional method is not copied correctly to the property's instance.

Am I missing something critical?

import Foundation

@objc protocol OptionalDelegate: class {
   @objc optional func doTheOptionalThing()
}

protocol NonOptionalDelegate: class {
   func doTheNonOptionalThing()
}

protocol MyProtocol: OptionalDelegate, NonOptionalDelegate {
    
}

extension OptionalDelegate where Self: MyProtocol {
   func doTheOptionalThing() {
      print("I am doing the OPTIONAL thing!")
   }
    
   func doTheNonOptionalThing() {
      print("I am doing the NON OPTIONAL thing!")
   }    
}

class TestWithoutOptionalImpl: NSObject, MyProtocol {
    
}

class TestWithOptionalImpl: NSObject, MyProtocol {
   func doTheOptionalThing() {
      print("I am doing the OPTIONAL thing by overwriting implemenation in class")
   }
}

class TestDelegator {
   weak var delegateOptional: OptionalDelegate?
   weak var delegateNonOptional: NonOptionalDelegate?   

   func goAhead(){
      guard let delegateOptional = delegateOptional else { return}
      delegateOptional.doTheOptionalThing?()
        
      guard let delegateNonOptional = delegateNonOptional else { return}
      delegateNonOptional.doTheNonOptionalThing()
   }
}

print("--- Testing direct invokation ---")
let testWithoutOptionalImpl = TestWithoutOptionalImpl()
testWithoutOptionalImpl.doTheOptionalThing()
testWithoutOptionalImpl.doTheNonOptionalThing()

print("--- Testing for indirection through property ---")
let testDelegator = TestDelegator()
testDelegator.delegateOptional = testWithoutOptionalImpl
// 1. Testing if the the instance is actually assigned
print("Do we have an instance stored in the property? -> \(testDelegator.delegateOptional)" )

// 2. Is not invoking doTheOptionalThing() 
testDelegator.delegateOptional?.doTheOptionalThing?()
testDelegator.delegateNonOptional = testWithoutOptionalImpl

// 3. Is not invoking doTheOptionalThing() 
testDelegator.goAhead()

print("--- Testing for indirection through property with a direct implementation in class ---")
let testWithOptionalImpl = TestWithOptionalImpl()
testDelegator.delegateOptional = testWithOptionalImpl
testDelegator.delegateNonOptional = testWithOptionalImpl
testDelegator.goAhead()

Output

--- Testing direct invokation ---
I am doing the OPTIONAL thing!
I am doing the NON OPTIONAL thing!
--- Testing for indirection through property ---
Do we have an instance stored in the property? -> Optional(<main.TestWithoutOptionalImpl: 0x7fa13b600240>)
I am doing the NON OPTIONAL thing!
--- Testing for indirection through property with a direct implementation in class ---
I am doing the OPTIONAL thing by overwriting implemenation in class
I am doing the NON OPTIONAL thing!

Expected Output

--- Testing direct invokation ---
I am doing the OPTIONAL thing!
I am doing the NON OPTIONAL thing!
--- Testing for indirection through property ---
Do we have an instance stored in the property? -> Optional(<main.TestWithoutOptionalImpl: 0x7fa13b600240>)
I am doing the OPTIONAL thing!
I am doing the OPTIONAL thing!
I am doing the NON OPTIONAL thing!
--- Testing for indirection through property with a direct implementation in class ---
I am doing the OPTIONAL thing by overwriting implemenation in class
I am doing the NON OPTIONAL thing!
@belkadan
Copy link
Contributor

Yeah, I'm afraid there's not a good way to implement this.

@swift-ci swift-ci transferred this issue from apple/swift-issues Apr 25, 2022
This issue was closed.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug A deviation from expected or documented behavior. Also: expected but undesirable behavior.
Projects
None yet
Development

No branches or pull requests

2 participants