在Swift中可以吗?如果不是,那么是否有解决方法?
当前回答
这里有一个非常简单的例子,只适用于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!)
}
}
其他回答
这里的其他答案涉及将协议标记为“@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
下面是一个使用委托模式的具体示例。
设置您的协议:
@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?()
让我们先来了解一下它们的区别
第一个例子-如果你写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)
}
}
如果你想在纯swift中做到这一点,最好的方法是提供一个默认实现,特别是如果你返回一个swift类型,例如struct与swift类型
例子:
struct magicDatas {
var damagePoints : Int?
var manaPoints : Int?
}
protocol magicCastDelegate {
func castFire() -> magicDatas
func castIce() -> magicDatas
}
extension magicCastDelegate {
func castFire() -> magicDatas {
return magicDatas()
}
func castIce() -> magicDatas {
return magicDatas()
}
}
然后你可以实现协议而不定义每个func
在协议中定义函数并为该协议创建扩展,然后为您想要作为可选使用的函数创建空实现。
推荐文章
- iOS如何设置应用程序图标和启动图像
- 更改UITextField和UITextView光标/插入符颜色
- 如何使用@Binding变量实现自定义初始化
- 'Project Name'是通过优化编译的——步进可能会表现得很奇怪;变量可能不可用
- Swift设置为Array
- 如何设置回退按钮文本在Swift
- 我如何能在Swift扩展类型化数组?
- Swift类错误:属性未在super处初始化。init调用
- 模拟器慢动作动画现在打开了吗?
- 如何为TableView创建NSIndexPath
- 滑动删除和“更多”按钮(就像iOS 7的邮件应用程序)
- 使UINavigationBar透明
- 如何改变推和弹出动画在一个基于导航的应用程序
- 删除/重置核心数据中的所有条目?
- Swift to Objective-C头未在Xcode 6中创建