我从Java \ C#背景进入Swift并且无法弄明白一件事。
有没有办法在Swift对象中创建类似于C#中事件(Action<T>
)的通知事件?
或者我想为此目的使用闭包?
答案 0 :(得分:1)
您可以使用委托和协议执行此操作。这是一个简单的例子,假设您有一个带有2个ViewControllers的Storyboard,名为ViewController和SecondViewController(故事板ID为“Main”)。
protocol SampleProtocol: class {
func didLoad()
func didAppear()
}
class ViewController: UIViewController, SampleProtocol {
override func viewDidLoad() {
super.viewDidLoad()
let secondViewController = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SecondVC") as! SecondViewController
secondViewController.configure(delegate: self)
addChildViewController(secondViewController)
view.addSubview(secondViewController.view)
}
func didLoad() {
print ("didLoad")
}
func didAppear() {
print ("didAppear")
}
}
class SecondViewController: UIViewController {
weak var delegate: SampleProtocol?
override func viewDidLoad() {
super.viewDidLoad()
delegate?.didLoad()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
delegate?.didAppear()
}
func configure(delegate: SampleProtocol) {
self.delegate = delegate
}
}
答案 1 :(得分:0)
正如我所理解的,C#中的Action<T>
委托只是一个Void
- 返回函数委托,它封装了一个可以通过委托执行的方法。
由于Swift支持更高阶函数,因此您可以定义自己的Action<T>
类型,其唯一目的是为类型所有者类型T的单个参数封装Void
- 返回方法。
struct Action<T> {
private let f: (T) -> ()
init(_ f: @escaping (T) -> ()) {
self.f = f
}
func run(_ val: T) {
f(val)
}
}
我们可以使用这个,例如封装函数:
func addOneAndPrint(val: Int) {
print(val+1)
}
let increaseAndPrintAction = Action(addOneAndPrint) // inferred to Action<Int>
increaseAndPrintAction.run(1) //2
或提供的闭包(类似于在C#中向Action<T>
提供lambda):
let increaseAndPrintAction = Action { print($0 + 1) }
increaseAndPrintAction.run(1) // 2
[1, 3, 5].forEach(increaseAndPrintAction.run) // 2 4 6
现在,我不知道C#中Action<T>
的常见用例,但是如果您想在完成某项任务时使用它来执行某些事件,您可能只想使用完成处理程序作为要执行的任务的闭包提供:
func increaseTask(_ val: inout Int, completion: (Int) -> ()) {
val += 1
// ...
completion(val)
}
var val = 1
increaseTask(&val) { print("Successfully increased to value \($0)") }
// Successfully increased to value 2
print(val) // 2
答案 2 :(得分:0)
正如其他人所说,swift 中没有 event
关键字。但实施您的方法很容易。
我已经完成了符合这些要求的 swift package。
source code 非常简单,不到 100 个 sloc。
这是一个简短的版本:
public class Event<T> {
private var handlers:[EventHandler<T>] = []
private init() {}
private func invoke(sender:AnyObject?,value:T) -> Void {
for handler in self.handlers {
handler.handle(sender,value)
}
}
public static func += ( event: Event, handler: EventHandler<T>) -> Void {
{
event.handlers.append(handler)
}
public static func -= ( event: Event, handler: EventHandler<T>) -> Void {
event.handlers.removeAll{$0 === handler}
}
public static func create() -> (invoke:Delegate<T>,event:Event<T>){
let res = Event<T>()
return (res.invoke,res)
}
}
EventHandler
在哪里
///needed as Swift doesn't allow func ===
public class EventHandler<T> {
private var _handle:Delegate<T>
public var handle:Delegate<T> {
return self._handle
}
public init(handle:@escaping Delegate<T>){
self._handle = handle
}
}
而 Delegate
是
public typealias Delegate<T> = (_ sender:AnyObject?,_ args:T) -> Void
使用 asis :
let tmp = Event<String>.create()
var handler = EventHandler<String>(handle: { sender, args in
print(args)
})
tmp.event += handler
tmp.invoke(self,"Hello world !")
//handler should print "Hello world !"
tmp.event -= handler
此解决方案提供与 C# 几乎相同的语法:+=
、-=
、Invoke
并防止在声明范围之外调用 invoke
。