"SE-0176-0186: Remove ownership keyword support in protocols" (Pull Request, Proposal, Discussion) made it a warning to specify weak
on Swift properties (vars) in protocols.
In other words this now generates a warning:
protocol MyProtocol {
// 'weak' should not be applied to a property declaration in a protocol
// and will be disallowed in future versions
weak var delegate: MyDelegate?
}
Instead, weak can be omitted from the protocol declaration, and Swift implementions of this protocol can redeclare the property as weak themselves:
class Impl: MyProtocol {
weak var delegate: MyDelegate?
}
However, this is a problem for ObjC implementations (as of the Xcode 9.3 betas which brought in this warning) since the compiler complains if you redeclare the property and change the strong/weakness:
#import <MyFramework-Swift.h>
@interface ImplObjC : NSObject <MyProtocol>
// warning: 'retain (or strong)' attribute on property 'delegate' does
// not match the property inherited from 'MyProtocol'
// [-Wproperty-attribute-mismatch]
@property (nonatomic, weak, nullable) id<MyDelegate> delegate;
@end
Alternatively in a private category:
@interface ImplObjC ()
// error: illegal redeclaration of property in class extension 'ImplObjC'
// (attribute must be 'readwrite', while its primary must be 'readonly')
@property (nonatomic, weak, nullable) id<MyDelegate> delegate;
@end
Alternatively synthesizing into a different ivar with __weak:
@interface ImplObjC ()
{
// error: existing instance variable 'm_delegate' for strong property
// 'delegate' may not be __weak
__weak id<MyDelegate> m_delegate;
}
@end
@implementation ImplObjC
@synthesize delegate = m_delegate;
@end
The only alternative that works is to override the setter and getter for the property and back it with a weak ivar/property. This is ugly and tedious.
We build with "warnings as errors" for ObjC, so this is a source breaking change for our existing code. It doesn't seem like it would be a good idea to ignore the Wproperty-attribute-mismatch warning. This is a problem for any existing ObjC code that implements Swift protocols like this.
Now, there are legitimate design discussions to be had over whether a delegate property belongs on an abstract protocol, but given how common the (weak) delegate pattern is in ObjC I believe there will be a significant amount of this kind of code in the wild (we ran into this at least).
Is this a known/expected issue and what is the suggested change?
Note: I've also posted this to the apple developer forums (https://forums.developer.apple.com/message/298704 - still waiting for moderator approval however). I was a little worried this is too ObjC-specific for the Swift forums but I feel like this fits under the "Using Swift" category.