Sel*_*vin 340 ios swift swift-extensions swift-protocols
在Swift中有可能吗?如果没有,那么有解决方法吗?
aka*_*kyy 464
如果要使用可选方法,则必须使用NSObject属性标记协议:
protocol MyProtocol {
func doSomething()
}
extension MyProtocol {
func doSomething() {
/* return a default value or just leave empty */
}
}
struct MyStruct: MyProtocol {
/* no compile error */
}
Run Code Online (Sandbox Code Playgroud)
否则,Swift协议的行为类似于其他OO语言上的接口,其中必须实现接口中定义的所有方法.
Ant*_*ine 393
在Swift 2及更高版本中,可以添加协议的默认实现.这为协议中的可选方法创建了一种新方法.
protocol MyProtocol {
func doSomethingNonOptionalMethod()
func doSomethingOptionalMethod()
}
extension MyProtocol {
func doSomethingOptionalMethod(){
// leaving this empty
}
}
Run Code Online (Sandbox Code Playgroud)
它在创建可选协议方法方面不是一个非常好的方法,但是您可以在协议回调中使用结构.
我在这里写了一个小摘要:https: //www.avanderlee.com/swift-2-0/optional-protocol-methods/
小智 39
由于有一些关于如何使用可选修饰符和@objc属性来定义可选需求协议的答案,我将给出一个关于如何使用协议扩展定义可选协议的示例.
下面的代码是Swift 3.*.
/// Protocol has empty default implementation of the following methods making them optional to implement:
/// `cancel()`
protocol Cancelable {
/// default implementation is empty.
func cancel()
}
extension Cancelable {
func cancel() {}
}
class Plane: Cancelable {
//Since cancel() have default implementation, that is optional to class Plane
}
let plane = Plane()
plane.cancel()
// Print out *United Airlines can't cancelable*
Run Code Online (Sandbox Code Playgroud)
请注意,Objective-C代码无法调用协议扩展方法,更糟糕的是Swift团队无法修复它.https://bugs.swift.org/browse/SR-492
Rap*_*ael 33
以下是委托模式的具体示例.
设置您的协议:
@objc protocol MyProtocol:class
{
func requiredMethod()
optional func optionalMethod()
}
class MyClass: NSObject
{
weak var delegate:MyProtocol?
func callDelegate()
{
delegate?.requiredMethod()
delegate?.optionalMethod?()
}
}
Run Code Online (Sandbox Code Playgroud)
将委托设置为类并实现协议.请注意,不需要实现可选方法.
class AnotherClass: NSObject, MyProtocol
{
init()
{
super.init()
let myInstance = MyClass()
myInstance.delegate = self
}
func requiredMethod()
{
}
}
Run Code Online (Sandbox Code Playgroud)
一个重要的是可选方法是可选的,需要一个"?" 在打电话时.提到第二个问号.
delegate?.optionalMethod?()
Run Code Online (Sandbox Code Playgroud)
Zag*_*Zag 32
这里涉及将协议标记为"@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"
Run Code Online (Sandbox Code Playgroud)
为了声明与swift一起使用的可选协议,将函数声明为变量而不是func.
protocol Health {
var isInfoHealthy: (Info) -> (Bool)? { get set }
}
Run Code Online (Sandbox Code Playgroud)
然后按如下方式实施协议
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)?
}
Run Code Online (Sandbox Code Playgroud)
然后你可以用"?" 检查功能是否已实施
func returnEntity() -> Health {
return Human()
}
var anEntity: Health = returnEntity()
var isHealthy = anEntity.isInfoHealthy(Info(height: 75, weight: 150))?
//"isHealthy" is true
Run Code Online (Sandbox Code Playgroud)
Gau*_*iya 31
在Swift 3.0中
@objc protocol CounterDataSource {
@objc optional func increment(forCount count: Int) -> Int
@objc optional var fixedIncrement: Int { get }
}
Run Code Online (Sandbox Code Playgroud)
它会节省您的时间.
Meh*_*mar 27
optional在每个方法之前添加关键字.gue*_*nis 12
具有协议继承的纯Swift方法:
//Required methods
protocol MyProtocol {
func foo()
}
//Optional methods
protocol MyExtendedProtocol: MyProtocol {
func bar()
}
class MyClass {
var delegate: MyProtocol
func myMethod() {
(delegate as? MyExtendedProtocol).bar()
}
}
Run Code Online (Sandbox Code Playgroud)
eLi*_*lie 11
为了说明Antoine答案的机制:
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"
Run Code Online (Sandbox Code Playgroud)
我想在询问如何实现可选的协议方法之前,你应该问为什么要实现一个.
如果我们将swift协议视为经典面向对象编程中的接口,则可选方法没有多大意义,也许更好的解决方案是创建默认实现,或将协议分成一组协议(可能具有一些继承关系)它们之间)代表协议中可能的方法组合.
有关进一步阅读,请参阅https://useyourloaf.com/blog/swift-optional-protocol-methods/,其中提供了有关此问题的出色概述.
从原始问题略微偏离主题,但它建立了Antoine的想法,我认为它可能会帮助某人.
对于具有协议扩展的结构,您还可以使计算属性可选.
您可以在协议上创建属性可选
protocol SomeProtocol {
var required: String { get }
var optional: String? { get }
}
Run Code Online (Sandbox Code Playgroud)
在协议扩展中实现虚拟计算属性
extension SomeProtocol {
var optional: String? { return nil }
}
Run Code Online (Sandbox Code Playgroud)
现在,您可以使用已实现或未实现可选属性的结构
struct ConformsWithoutOptional {
let required: String
}
struct ConformsWithOptional {
let required: String
let optional: String?
}
Run Code Online (Sandbox Code Playgroud)
我还在我的博客上写了如何在Swift协议中做可选属性,如果通过Swift 2版本发生变化,我会不断更新.
有两种方法可以在 swift 协议中创建可选方法。
1 - 第一个选项是使用 @objc 属性标记您的协议。虽然这意味着它只能被类采用,但这确实意味着您将单个方法标记为可选,如下所示:
@objc protocol MyProtocol {
@objc optional func optionalMethod()
}
Run Code Online (Sandbox Code Playgroud)
2 - 更快捷的方式:此选项更好。像这样编写什么都不做的可选方法的默认实现。
protocol MyProtocol {
func optionalMethod()
func notOptionalMethod()
}
extension MyProtocol {
func optionalMethod() {
//this is a empty implementation to allow this method to be optional
}
}
Run Code Online (Sandbox Code Playgroud)
Swift 有一个叫做 extension 的特性,它允许我们为那些我们希望是可选的方法提供默认实现。
如何创建可选的和必需的委托方法。
@objc protocol InterViewDelegate:class {
@objc optional func optfunc() // This is optional
func requiredfunc()// This is required
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
147256 次 |
| 最近记录: |