【问题标题】:Handler Method in #selector Swift 2.2#selector Swift 2.2 中的处理程序方法
【发布时间】:2016-05-18 14:20:24
【问题描述】:

我的想法是创建一种简单的方法来向按钮添加事件方法。

按照我的例子: Gist

问题是我遇到了 EXC_BAD_ACCESS 问题,可能是因为 #selector 中的执行不安全。

将是一种修复或更改以解决它的方法吗?

调试屏幕:

堆栈跟踪:

* thread #1: tid = 0x4e8e43, 0x0000000110355547 libsystem_blocks.dylib`_Block_copy_internal + 239, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=EXC_I386_GPFLT)
frame #0: 0x0000000110355547 libsystem_blocks.dylib`_Block_copy_internal + 239
frame #1: 0x000000010d8c326d Swift-201-Aula2-Exercicio2.1`@objc UICallbackButton.executeCallback(UIButton, callback : (button : UIButton) -> ()) -> () + 45 at ViewController.swift:0
frame #2: 0x000000010e2d4a8d UIKit`-[UIApplication sendAction:to:from:forEvent:] + 92
frame #3: 0x000000010e447e67 UIKit`-[UIControl sendAction:to:forEvent:] + 67
frame #4: 0x000000010e448143 UIKit`-[UIControl _sendActionsForEvents:withEvent:] + 327
frame #5: 0x000000010e447263 UIKit`-[UIControl touchesEnded:withEvent:] + 601
frame #6: 0x000000010e34799f UIKit`-[UIWindow _sendTouchesForEvent:] + 835
frame #7: 0x000000010e3486d4 UIKit`-[UIWindow sendEvent:] + 865
frame #8: 0x000000010e2f3dc6 UIKit`-[UIApplication sendEvent:] + 263
frame #9: 0x000000010e2cd553 UIKit`_UIApplicationHandleEventQueue + 6660
frame #10: 0x000000010d9d0301 CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
frame #11: 0x000000010d9c622c CoreFoundation`__CFRunLoopDoSources0 + 556
frame #12: 0x000000010d9c56e3 CoreFoundation`__CFRunLoopRun + 867
frame #13: 0x000000010d9c50f8 CoreFoundation`CFRunLoopRunSpecific + 488
frame #14: 0x0000000112140ad2 GraphicsServices`GSEventRunModal + 161
frame #15: 0x000000010e2d2f09 UIKit`UIApplicationMain + 171
* frame #16: 0x000000010d8c42c2 Swift-201-Aula2-Exercicio2.1`main + 114 at AppDelegate.swift:12
frame #17: 0x000000011031292d libdyld.dylib`start + 1

【问题讨论】:

  • 显示堆栈跟踪和它所指的代码行。
  • 我用屏幕更新了问题,问题是我没有堆栈跟踪。
  • 在调试控制台中输入bt
  • 谢谢,添加了堆栈跟踪。我更新了 gist 文件中的一些类和方法名称。

标签: swift uibutton xcode7.3 swift2.2


【解决方案1】:

我相信您的代码有几个问题。按钮上的循环引用(可能不是问题),但可以肯定的是,您的回调不会一直到 executeCallback(:) 方法。事实证明你不需要它。只需保存对回调的引用。看看这是否有意义。它有效。

import UIKit

class ViewController: UIViewController {

    var count = 1

    override func viewDidLoad() {
        super.viewDidLoad()

        // Button 1
        let button = UICallbackButton(frame: CGRect(x: 60, y: 30, width: 200, height: 60))
        button.backgroundColor = UIColor.orangeColor()
        button.setTitleColor(UIColor.whiteColor(), forState: .Normal)
        button.setTitle("Title Default", forState: .Normal)
        button.on(.TouchUpInside, then: {
            button.setTitle("Title \(self.count)", forState: .Normal)
            self.count = self.count + 1
        })

        self.view.addSubview(button)


        // Button 2
        let button1 = UICallbackButton(frame: CGRect(x: 60, y: 160, width: 200, height: 60))
        button1.backgroundColor = UIColor.blackColor()
        button1.setTitleColor(UIColor.whiteColor(), forState: .Normal)
        button1.setTitle("Value Default", forState: .Normal)
        button1.on(.TouchUpInside, then: {
            button1.setTitle("Value \(self.count)", forState: .Normal)
            self.count = self.count + 1
        })

        self.view.addSubview(button1)

    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

}


typealias ButtonCallback = (() -> ())

protocol UIActionButton {

    func on(event : UIControlEvents, then callback: ButtonCallback)

}

final class UICallbackButton : UIButton, UIActionButton {

    var buttonCallback: ButtonCallback!

    func on(event : UIControlEvents, then callback: ButtonCallback) {
        buttonCallback = callback
        self.addTarget(self, action: #selector(UICallbackButton.executeCallback(_:)), forControlEvents: event)

    }

    func executeCallback (_ : UIButton) {
        buttonCallback()
    }
}

【讨论】:

    【解决方案2】:

    老实说,我不知道如何使用选择器来做到这一点,但这里有一个闭包。测试和工作 100%。我将尝试使用选择器找到解决方案。不可能有那么大的不同。你可以传递一个控制事件数组,它会占所有的。

    import UIKit
    
    class ViewController: UIViewController {
    
        var count = 1
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        // Button 1
        let button = GIBbutton(frame: CGRect(x: 60, y: 30, width: 200, height: 60), controlEvents: [.TouchUpInside], targetAction: { button in
            button.setTitle("Title \(self.count)", forState: .Normal)
            self.count += 1
        })
        button.backgroundColor = UIColor.orangeColor()
        button.setTitleColor(UIColor.whiteColor(), forState: .Normal)
        button.setTitle("Title Default", forState: .Normal)
    
    
        self.view.addSubview(button)
    
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    

    }

    类 GIBbutton : UIButton{ var action : ((UIButton!)->Void)!

    convenience init(frame:CGRect,controlEvents:[UIControlEvents],targetAction:((UIButton!)->Void)!){
        self.init()
        self.frame = frame
        action = targetAction
        for event in controlEvents{
            self.addTarget(self, action: #selector(GIBbutton.performOurAction), forControlEvents: event)
        }
    }
    
    func performOurAction(button:UIButton,completion:(UIButton)){
        self.action(self)
    }
    

    }

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2016-10-17
      • 1970-01-01
      • 1970-01-01
      • 2016-07-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多