繁体   English   中英

为什么@optional 修改的属性会变成不可变的?

[英]Why do properties modified by @optional become immutable?

我有一个包含如下属性的Objective-C协议:

#import <Foundation/Foundation.h>

@protocol Playback <NSObject>

@optional

@property (nonatomic, nonnull) NSURL *assetURL;

@end

PlayerController有一个id<Playback>类型的属性:

@interface PlayerController: NSObject

@property (nonatomic, strong, nonnull) id<Playback> currentPlayerManager;

@end

我尝试在Swift中编写以下代码,但出现错误

var player = PlayerController()
var pla = player.currentPlayerManager

pla.assetURL = URL(string: "123") // ❌ Cannot assign to property: 'pla' is immutable

如果我注释掉Playback协议的@optional ,那么它编译得很好。

这让我想知道为什么@optional会导致这个错误?

由于它是可选的,Swift 不能保证 setter 的实现。

来自论坛上的Jordan Rose(在实施SE-0070时从事 Swift 工作):

通常可选要求会增加额外的可选性:

  • 方法本身成为可选的( f.bar?()
  • 属性 getter 将值包装在Optional的额外级别( if let bar = f.bar

但是对于属性设置器来说,没有地方可以放置额外的 Optional 级别。 这就是整个故事:我们从来没有想出如何以安全的方式公开可选的属性设置器,并且不想选择任何特定的不安全解决方案。 如果有人能想到一些很棒的东西!

所以答案似乎是:在optional协议要求被故意限制为 Swift ( SE-0070 ) 中的 Objective-C 协议时,没有决定明确实现的拼写,而且看起来这个功能并不常见,以至于从那以后就没有真正出现过。

直到(如果)这被支持,有两种潜在的解决方法:

  1. Playback引入一个显式方法,该方法为assetURL

    • 遗憾的是,此方法不能命名为-setAssetURL:因为它将被导入 Swift 中,就好像它是属性设置器而不是方法一样,您仍然无法调用它。 (如果您将assetURL标记为readonly ,这仍然是正确的)
    • 同样可悲的是,此方法将无法具有默认实现,因为 Objective-C 不支持默认协议实现,并且您无法在 Swift extension中为该方法提供实现,因为您仍然无法分配给协议
  2. 像在 Swift 中那样做,并引入协议层次结构,例如, AssetBackedPlayback协议继承自Playback并提供assetURL作为非@optional

     @protocol Playback <NSObject> // Playback methods @end @protocol AssetBackedPlayback: Playback @property (nonatomic, nonnull) NSURL *assetURL; @end

    然后,您需要找到一种方法将PlayerController.currentPlayerManager公开为AssetBackedPlayback以便分配assetURL


约旦的一些其他替代品:

我认为最初推荐的解决方法是“在 Objective-C 中编写一个static inline function 来为你做这件事”,但这也不是很好。 如果setValue(_:forKey:)不在热门路径中,它在实践中也足够好。

The static inline function recommendation can function similarly to a default protocol implementation, but you do need to remember to call that function instead of accessing the property directly.

setValue(_:forKey:)也可以工作,但会导致明显的性能损失,因为它通过 Objective-C 运行时支持很多动态,并且比简单的分配要复杂得多。 根据您的用例,成本可能是可以接受的,以避免复杂性!

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM