包含响应addtarget函数的类或父类

时间:2015-12-09 22:16:42

标签: ios swift

我在理解addtarget的工作原理时遇到了一些麻烦。我在下面的快速课程中复制了我的问题。该按钮在屏幕上正确显示,但是当我按下它时,scala> case class Calendar(id:Int,name:String,description:Option[String],owner:Int) defined class Calendar scala> case class CalendarRow(id:Int,name:String,description:Option[String],settings:Seq[String]=Seq.empty) defined class CalendarRow scala> def append(calendars:Calendar*) = calendars.map(c => CalendarRow(c.id,c.name,c.description)) append: (calendars: Calendar*)Seq[CalendarRow] scala> val calendar1 = Calendar(1,"first",Option("my first calendar"),1) calendar1: Calendar = Calendar(1,first,Some(my first calendar),1) scala> val calendar2 = Calendar(2, "second",None,1) calendar2: Calendar = Calendar(2,second,None,1) scala> val list = append(calendar1,calendar2) list: Seq[CalendarRow] = ArrayBuffer(CalendarRow(1,first,Some(my first calendar),List()), CalendarRow(2,second,None,List())) 功能被调用而不是PopupMenuViewController.pressed功能。
为什么吗

handlerClass.pressed

FIX:感谢Carl指出这一点。应将import Foundation import UIKit import CoreLocation class PopupMenuViewController : UIViewController { class handlerClass { func pressed(sender: UIButton!) { /// **IT SEEMS LIKE THE CALL FROM ADDTARGET SHOULD GO HERE...** var alertView = UIAlertView(); alertView.addButtonWithTitle("Ok"); alertView.title = "title"; alertView.message = "message"; alertView.show(); } } func pressed(sender: UIButton!) { // **BUT INSTEAD IT ENDS UP HERE!!!!** var alertView = UIAlertView(); alertView.addButtonWithTitle("Ok"); alertView.title = "title"; alertView.message = "message"; alertView.show(); } override func viewDidLoad() { super.viewDidLoad() let hc = handlerClass() // make me a member variable to fix this problem let button1 = UIButton() button1.frame = CGRectMake(10, 400, 100, 50) button1.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.9) button1.layer.cornerRadius = 10.0 button1.setTitle("Button ", forState: UIControlState.Normal) // ** THE OFFENDING ADD TARGE CALL ** button1.addTarget(hc, action: "pressed:", forControlEvents: .TouchUpInside) self.view.addSubview(button1) } } 提升为成员变量

3 个答案:

答案 0 :(得分:1)

来自Apple docs

  

目标对象 - 即操作所针对的对象   邮件已发送。如果为零,则搜索响应者链   愿意回应行动信息的对象。

但是你指定了目标对象,那么最近怎么办?另一个有趣的引用:

  

调用此方法时,不会保留目标。

你在一个函数中创建了这个对象,只存储在那里,所以一旦块结束,保留计数结束于0,变量现在为零。

为避免这种情况,您可以在函数之前将其作为属性添加,然后在函数中实例化。

答案 1 :(得分:0)

感谢卡尔的评论。

最初的问题实际上有点复杂,我在长按识别器中创建了一个PopupMenuViewController。

   func mapView(mapView: GMSMapView!, didLongPressAtCoordinate coordinate: CLLocationCoordinate2D)
   {
     let tapPoint = coordinate

     let menu = PopupMenuViewController();

     self.presentVC(menu)

     // menu is deallocated before exit (and before it can respond to pressed)
   }

PopupMenuViewController中的被按下的函数在它响应之前被销毁了。

答案 2 :(得分:0)

我想我知道造成这种奇怪行为的原因。首先,您的let hc = handlerClass()变量不会保留在viewDidLoad范围之外。换句话说,在viewDidLoad完成运行后,它实际上不再存在。

每当你使用目标行动模式时,你需要保证当事件被触发时,目标仍在某个地方。

根据另一个答案进行更新:因为hc变量已被释放,但触发了操作的时间,最终被调用的对象是响应者链上的下一个响应pressed:的对象

对此的一个解决方案是向父类添加var handler: HandlerClass?,并在创建处理程序时存储处理程序。

但是,当我在本地测试中执行此操作时,我遇到了另一个奇怪的错误,即(处理程序类的)实例没有响应pressed:。直到我从NSObject下降HandlerClass后才能按预期工作。这是我最终得到的工作示例:

import UIKit

class ViewController: UIViewController {
    var handler: HandlerClass?

    class HandlerClass : NSObject
    {
        func pressed(sender: UIButton!) {
            /// **THE CALL FROM ADD TARGET ENDS UP HERE**
            let alertView = UIAlertView();
            alertView.addButtonWithTitle("Ok");
            alertView.title = "HandlerClass";
            alertView.message = "HandlerClass";
            alertView.show();
        }
    }

    func pressed(sender: UIButton!) {
        // **NOT HERE**
        let alertView = UIAlertView();
        alertView.addButtonWithTitle("Ok");
        alertView.title = "non handler pressed";
        alertView.message = "non handler message";
        alertView.show();
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        // let hc = HandlerClass()

        let button1 = UIButton()
        button1.frame = CGRectMake(100, 100, 100, 100)
        button1.backgroundColor =      UIColor.lightGrayColor().colorWithAlphaComponent(0.9)
        button1.layer.cornerRadius = 10.0
        button1.setTitle("Button ", forState: UIControlState.Normal)

        view.addSubview(button1)

        handler = HandlerClass()

        button1.addTarget(handler, action: "pressed:", forControlEvents: .TouchUpInside)
    }

}