在Swift中可以吗?如果不是,那么是否有解决方法?


当前回答

下面是一个使用委托模式的具体示例。

设置您的协议:

@objc protocol MyProtocol:class
{
    func requiredMethod()
    optional func optionalMethod()
}

class MyClass: NSObject
{
    weak var delegate:MyProtocol?

    func callDelegate()
    {
        delegate?.requiredMethod()
        delegate?.optionalMethod?()
    }
}

将委托设置为类并实现协议。请注意,不需要实现可选方法。

class AnotherClass: NSObject, MyProtocol
{
    init()
    {
        super.init()

        let myInstance = MyClass()
        myInstance.delegate = self
    }

    func requiredMethod()
    {
    }
}

重要的一点是,可选方法是可选的,在调用时需要“?”。提到第二个问号。

delegate?.optionalMethod?()

其他回答

在Swift 2及以后的版本中,可以添加协议的默认实现。这为协议中的可选方法提供了一种新的方式。

protocol MyProtocol {
    func doSomethingNonOptionalMethod()
    func doSomethingOptionalMethod()
}

extension MyProtocol {
    func doSomethingOptionalMethod(){ 
        // leaving this empty 
    }
}

这不是一个创建可选协议方法的好方法,但是给了你在协议回调中使用struct的可能性。

我在这里写了一个小总结: https://www.avanderlee.com/swift-2-0/optional-protocol-methods/

这里有一个非常简单的例子,只适用于swift类,而不适用于结构或枚举。 注意,协议方法是可选的,有两个级别的可选链接。 同样,采用协议的类在声明中需要@objc属性。

@objc protocol CollectionOfDataDelegate{
   optional func indexDidChange(index: Int)
}


@objc class RootView: CollectionOfDataDelegate{

    var data = CollectionOfData()

   init(){
      data.delegate = self
      data.indexIsNow()
   }

  func indexDidChange(index: Int) {
      println("The index is currently: \(index)")
  }

}

class CollectionOfData{
    var index : Int?
    weak var delegate : CollectionOfDataDelegate?

   func indexIsNow(){
      index = 23
      delegate?.indexDidChange?(index!)
    }

 }

在Swift 3.0中

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

这会节省你的时间。

这里的其他答案涉及将协议标记为“@objc”,在使用swift特定类型时不起作用。

struct Info {
    var height: Int
    var weight: Int
} 

@objc protocol Health {
    func isInfoHealthy(info: Info) -> Bool
} 
//Error "Method cannot be marked @objc because the type of the parameter cannot be represented in Objective-C"

为了声明能在swift中很好地工作的可选协议,将函数声明为变量而不是func。

protocol Health {
    var isInfoHealthy: (Info) -> (Bool)? { get set }
}

然后实现如下协议

class Human: Health {
    var isInfoHealthy: (Info) -> (Bool)? = { info in
        if info.weight < 200 && info.height > 72 {
            return true
        }
        return false
    }
    //Or leave out the implementation and declare it as:  
    //var isInfoHealthy: (Info) -> (Bool)?
}

然后可以使用“?”来检查函数是否已经实现

func returnEntity() -> Health {
    return Human()
}

var anEntity: Health = returnEntity()

var isHealthy = anEntity.isInfoHealthy(Info(height: 75, weight: 150))? 
//"isHealthy" is true

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

第一个例子-如果你写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)
    }
}