问题描述
我是 Swift 的新手,我正在尝试使用 typealias 将回调重写为委托,但我迷路了 :(
这是我的代码:
protocol NewNoteDelegate: class {
typealias MakeNewNote = ((String,String) -> Void)?
}
class NewNoteViewController: UIViewController {
@IBOutlet weak private var titleField: UITextField?
@IBOutlet weak private var noteField: UITextView!
weak var delegate: NewNoteDelegate?
// public var makeNewNote: ((String,String) -> Void)?
override func viewDidLoad() {
super.viewDidLoad()
titleField?.becomeFirstResponder()
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save",style: .done,target: self,action: #selector(didTapSave))
}
@objc func didTapSave() {
if let text = titleField?.text,!text.isEmpty,!noteField.text.isEmpty {
// makeNewNote?(text,noteField.text)
delegate?.MakeNewNote(text,noteField.text)
}
}
}
错误是:
- 无法将 'String' 类型的值转换为预期的参数类型 '(String,String) -> Void'
- 调用中的额外参数
原来的可选回调定义和调用被注释掉了。我首先尝试将 makeNewNote
重写为没有协议的类型别名,但仍然遇到相同的错误。
我也尝试从 ?
中删除 MakeNewNote
但产生了一个新错误:
- 类型 '(String,String) -> Void' 没有成员 'init'
我尝试了很多谷歌搜索,已经过了几个小时。任何人都可以帮助我找出问题所在或指出我正确的方向吗?提前致谢。
解决方法
你糊涂了。在协议中定义类型别名没有任何价值。您不妨将 typealias 设为全局。它只是定义了一个类型。您希望您的协议定义符合对象支持的方法和属性:
protocol NewNoteDelegate: class {
func makeNewNote(_: String,_: String)
}
这只是意味着任何符合 NewNoteDelegate 协议的对象都必须实现 makeNewNote(:,:) 函数。
我不确定函数 return Void?
到底有什么作用,所以我把它去掉了。
另请注意,函数带有两个匿名参数在 Swift 中被认为是不好的形式。您应该真正命名所有参数(可能除了第一个)。在 Swift 中,名称让您知道每个参数的用途。
考虑这个示例代码(编译为 Mac 命令行工具,但它也可以很容易地成为游乐场。我只是碰巧不喜欢游乐场。)
import Foundation
protocol NewNoteDelegate: class {
func makeNewNote(_: String,_: String)
}
//The Foo class has a delegate that conforms to the NewNoteDelegate protocol.
class Foo {
weak var delegate: NewNoteDelegate?
func doSomething(string1: String,string2: String) {
//Invoke our delegate,if we have one.
delegate?.makeNewNote(string1,string2)
}
}
//This class just knows how to be a NewNoteDelegate
class ADelegate: NewNoteDelegate {
func makeNewNote(_ string1: String,_ string2: String){
print("string 1 = '\(string1)',string 2 = '\(string2)'")
return
}
}
//Create a Foo object
let aFoo = Foo()
//Create an ADelegate object
let aDelegate = ADelegate()
//Make the ADelegate the Foo object's delegate
aFoo.delegate = aDelegate
//Tell our foo object to do something.
aFoo.doSomething(string1: "string 1",string2: "string 2")
该代码输出
string 1 = 'string 1',string 2 = 'string 2'