在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的类才能符合这样的协议。没有结构,没有枚举,没有关联类型。 必须始终通过可选调用或检查符合类型是否实现了可选方法来检查是否实现了可选方法。如果经常调用可选方法,这可能会引入大量样板文件。

在Swift 3.0中

@objc protocol CounterDataSource {
    @objc optional func increment(forCount count: Int) -> Int
    @objc optional var fixedIncrement: Int { get }
}

这会节省你的时间。

为了说明安托万回答的机制:

protocol SomeProtocol {
    func aMethod()
}

extension SomeProtocol {
    func aMethod() {
        print("extensionImplementation")
    }
}

class protocolImplementingObject: SomeProtocol {

}

class protocolImplementingMethodOverridingObject: SomeProtocol {
    func aMethod() {
        print("classImplementation")
    }
}

let noOverride = protocolImplementingObject()
let override = protocolImplementingMethodOverridingObject()

noOverride.aMethod() //prints "extensionImplementation"
override.aMethod() //prints "classImplementation"

让我们先来了解一下它们的区别

第一个例子-如果你写UITableViewDataSource,那么你需要强制写两个方法-这是默认协议的快速方式

第二个例子-如果你写UITableViewDelegate,并意识到它不会显示红色错误,请添加所有的委托方法。使用哪种方法取决于你自己。我们可以调用作为可选方法!

让我们通过一个例子来理解

第一种Swift方式默认协议方法

class ContactModel{
    var firstname: String?
    var lastname: String?
}

protocol ContactDataSource: AnyObject{
    func contactConfiguration(contact: ContactModel)
}

class ViewController: ContactDataSource{
    func contactConfiguration(contact: ContactModel) {
        print(contact)
    }
}

第二种方法——可选协议

@objc
class UserModel: NSObject{
    var firstname: String = ""
}

@objc protocol UserDataSource{
    func contactConfiguration(user: UserModel)
   @objc optional func userInfo(user: UserModel)
}

class ViewController: UserDataSource{
    func contactConfiguration(user: UserModel) {
        print(user)
    }
}

注意:如果你能在可选协议中看到,我还没有写userInfo方法,所以这取决于你。这意味着With和不向类添加方法 它工作得很好。-在协议中作为可选方法调用 类声明类和协议 @objc属性,它只与类而不是struct工作!

第三种方法-使用扩展的可选协议

注意:你可以选择Struct或Class

class UserModel{
    var firstname: String = ""
}

OR

struct UserModel{
    var firstname: String = ""
}

AND

protocol UserDataSource{
    func contactConfiguration(user: UserModel)
}

extension UserDataSource{
    func userInfo(user: UserModel){}
}

class myview: UserDataSource{
    func contactConfiguration(user: UserModel) {
        print(user)
    }
}

如何创建可选和必需的委托方法。

@objc protocol InterViewDelegate:class {

    @objc optional func optfunc()  //    This is optional
    func requiredfunc()//     This is required 

}