在Swift中可以吗?如果不是,那么是否有解决方法?
当前回答
一种选择是将它们存储为可选函数变量:
struct MyAwesomeStruct {
var myWonderfulFunction : Optional<(Int) -> Int> = nil
}
let squareCalculator =
MyAwesomeStruct(myWonderfulFunction: { input in return input * input })
let thisShouldBeFour = squareCalculator.myWonderfulFunction!(2)
其他回答
我认为在询问如何实现一个可选协议方法之前,应该先问问为什么要实现它。
如果我们将swift协议视为经典的面向对象编程中的接口,那么可选方法就没有多大意义,也许更好的解决方案是创建默认实现,或将协议分离为一组协议(可能在它们之间具有一些继承关系),以表示协议中方法的可能组合。
欲进一步阅读,请参阅https://useyourloaf.com/blog/swift-optional-protocol-methods/,该网站对此问题有很好的概述。
在Swift 3.0中
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
这会节省你的时间。
有两种方法可以在swift协议中创建可选方法。
1 -第一个选项是使用@objc属性标记你的协议。虽然这意味着它只能被类采用,但它确实意味着你可以像这样将单个方法标记为可选的:
@objc protocol MyProtocol {
@objc optional func optionalMethod()
}
2 -更快的方式:这个选择更好。编写什么都不做的可选方法的默认实现,如下所示。
protocol MyProtocol {
func optionalMethod()
func notOptionalMethod()
}
extension MyProtocol {
func optionalMethod() {
//this is a empty implementation to allow this method to be optional
}
}
Swift有一个叫做扩展的特性,它允许我们为那些我们想要成为可选的方法提供一个默认实现。
1. 使用默认实现(首选)。
protocol MyProtocol {
func doSomething()
}
extension MyProtocol {
func doSomething() {
/* return a default value or just leave empty */
}
}
struct MyStruct: MyProtocol {
/* no compile error */
}
优势
不涉及Objective-C运行时(好吧,至少没有显式地)。这意味着你可以使结构,枚举和非nsobject类符合它。此外,这意味着您可以利用强大的泛型系统。 当遇到符合这种协议的类型时,您总是可以确保满足所有需求。它总是具体实现或默认实现。这就是“接口”或“契约”在其他语言中的表现。
缺点
For non-Void requirements, you need to have a reasonable default value, which is not always possible. However, when you encounter this problem, it means that either such requirement should really have no default implementation, or that your you made a mistake during API design. You can't distinguish between a default implementation and no implementation at all, at least without addressing that problem with special return values. Consider the following example: protocol SomeParserDelegate { func validate(value: Any) -> Bool } If you provide a default implementation which just returns true — it's fine at the first glance. Now, consider the following pseudo code: final class SomeParser { func parse(data: Data) -> [Any] { if /* delegate.validate(value:) is not implemented */ { /* parse very fast without validating */ } else { /* parse and validate every value */ } } } There's no way to implement such an optimization — you can't know if your delegate implements a method or not. Although there's a number of different ways to overcome this problem (using optional closures, different delegate objects for different operations to name a few), that example presents the problem clearly.
2. 使用@objc可选。
@objc protocol MyProtocol {
@objc optional func doSomething()
}
class MyClass: NSObject, MyProtocol {
/* no compile error */
}
优势
不需要缺省实现。你只需要声明一个可选方法或变量就可以了。
缺点
它要求所有符合要求的类型都与Objective-C兼容,从而严重限制了协议的功能。这意味着,只有继承自NSObject的类才能符合这样的协议。没有结构,没有枚举,没有关联类型。 必须始终通过可选调用或检查符合类型是否实现了可选方法来检查是否实现了可选方法。如果经常调用可选方法,这可能会引入大量样板文件。
您需要在每个方法之前添加可选关键字。 但是,请注意,要使其工作,您的协议必须用@objc属性标记。 这进一步表明该协议将适用于类,但不适用于结构。
推荐文章
- iOS如何设置应用程序图标和启动图像
- 更改UITextField和UITextView光标/插入符颜色
- 如何使用@Binding变量实现自定义初始化
- 'Project Name'是通过优化编译的——步进可能会表现得很奇怪;变量可能不可用
- Swift设置为Array
- 如何设置回退按钮文本在Swift
- 我如何能在Swift扩展类型化数组?
- Swift类错误:属性未在super处初始化。init调用
- 模拟器慢动作动画现在打开了吗?
- 如何为TableView创建NSIndexPath
- 滑动删除和“更多”按钮(就像iOS 7的邮件应用程序)
- 使UINavigationBar透明
- 如何改变推和弹出动画在一个基于导航的应用程序
- 删除/重置核心数据中的所有条目?
- Swift to Objective-C头未在Xcode 6中创建