gpt4 book ai didi

ios - ViewControl 之外的 Swift 选择器

转载 作者:可可西里 更新时间:2023-11-01 00:17:58 26 4
gpt4 key购买 nike

我有一个 ViewController 及其 View :

class GraphicViewController: UIViewController {
var timerVC!:NSTimer
override func viewDidLoad() {
(view as GraphicView).timerV = NSTimer.scheduledTimerWithTimeInterval(interval, target: self, selector: Selector("doSomeWork"), userInfo: nil, repeats: true)

}
}


class GraphicView: UIView {
var timerV:NSTimer!
func doSomeWork(someParam:NSString)->Double {/*code*/}
}

它会导致有关错误选择器的错误。我有两个问题:

1) 如何使用带参数的 Selector 并从 func 返回?

2) 如何从 View 中选择函数而不是在 VC 中创建这样的函数?

最佳答案

触发错误的原因是您没有提供正确的目标。这就是目标- Action 范式的工作原理(或者至少,它在 Objective C 中的工作原理,我真的希望他们会更新 Swift API 以利用整个函数即对象的哲学):

  • 您有一个名为 target 的对象,它有一个名为 action 的方法,您希望外部调用者调用该方法。 (请注意,我正在对此进行简化,它实际上是 Objective C 运行时的东西)
  • 您有一个 API 调用,其签名中某处具有 target: (id)target, selector:(Selector)selector。这应该告诉您,该 API 计划调用您必须提供的对象上的方法,您也必须提供该对象。
  • 它们分别是您的目标和您的行动。由于您的 View 包含您希望 NSTimer 运行的方法,因此 View 将成为您的目标,而方法将成为您的操作。当您提供 self 作为目标时,您是在告诉 NSTimer 在您的 View Controller 上调用名为“doSomeWork”的方法,而该方法并未实现此类方法。难怪它会触发有关无法识别的选择器的错误!此外,如果您确实将 View 作为目标传递,那仍然会触发错误,因为与该方法关联的正确选择器将是 “doSomeWork:”,如 Objective C 方法签名中所示。

这是最接近的正确实现:

class GraphicViewController: UIViewController {
var timerVC!:NSTimer
override func viewDidLoad() {
let gView = view as GraphicView
gView.timerV = NSTimer.scheduledTimerWithTimeInterval(interval, target: gView, selector: Selector("doSomeWork"), userInfo: nil, repeats: true)

}
}


class GraphicView: UIView {
var timerV:NSTimer!
func doSomeWork() {/*code*/}
}

根据参数和返回:根据目标-操作范例,您不应使用所调用方法的任何返回值。 Target-action 为目标提供了一种与发送者对象(NSTimer)通信的机制:如果您提供的选择器不接受任何参数(即它不以冒号结尾),则调用该方法时不带任何参数;如果选择器确实需要一个参数(即它以冒号结尾),发送者将调用它作为唯一参数传递自己。显然,您必须相应地更新调用的方法:

class GraphicView: UIView {
var timerV:NSTimer!
func doSomeWork(sender: NSTimer!) {
/* do some work involving sender */
}
}

关于最后一个问题,如果我理解正确的话,你是在寻求一种方法来避免必须从 UIViewController 内部引用 GraphicView 中定义的方法。这实际上是可能的,但这不会让您在不使用目标操作的情况下设置 NSTimer(截至今天)。当然,实现整个事情的更方便的方法可能是:

class GraphicViewController: UIViewController {
override func viewDidLoad() {
let gView = view as GraphicView
gView.setupTimer()
}
}

class GraphicView: UIView {
var timer: NSTimer!
func doSomeWork(sender: NSTimer!) {
/* code */
}

func setupTimer() {
timer = NSTimer.scheduledTimerWithTimeInterval(interval, target: self, selector: Selector("doSomeWork:"), userInfo: nil, repeats: true)
}
}

在这个实现中,将 self 作为目标传递是有意义的,因为 View 正在设置计时器以在其自身上调用该方法。这样您就可以像上面那样创建一个临时常量,然后访问它的 timer 属性,从而从 View Controller 内部访问计时器。

关于ios - ViewControl 之外的 Swift 选择器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26512256/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com