1

我在工作中遇到了一个重大问题,非常感谢一些帮助。这已经花了我 2 天的时间。

我想要做的是有一个特殊的图像类触发它被触摸时分配回调。而已。

但是当我触摸图像时它崩溃了,通常没有错误消息(lldb)。有时它会说垃圾之类的"[__NSCFData tapped:]: unrecognized selector sent to instance 0x1780af360"。有时它说"message sent to deallocated object"

我可以连续运行该应用程序 10 次,只需每次点击屏幕上的同一个对象即可获得其中一条随机消息。

代码非常简单:

//view controller
var k:K_PreviewImage!
override func viewDidLoad()
    {
        var image:iImage = iImage(imageName: "ja3.jpg")
        k = K_PreviewImage(image: image)
        k.touchCallback = nestedTap
        _view.addSubview(k.image)
    }

   func nestedTap(k:K_PreviewImage)
    {
        println("Successs")
    }

这是里面的代码K_PreviewImage(我的可点击图片)。这不会从任何东西继承,包括 NSObject

var touchCallback:((K_PreviewImage)->Void)
    {
        set{
            if(_touchCallback == nil)
            {
                var tap:UIGestureRecognizer = UITapGestureRecognizer(target: self, action:"tapped:")
                _image.addGestureRecognizer(tap)
            }

            _touchCallback = newValue
        }
        get{
            return _touchCallback
        }

  func tapped(tap:UITapGestureRecognizer)
    {
        println("here")
        if(_touchCallback != nil)
        {
            touchCallback(self)
        }
    }

上面的代码在 100% 的情况下都会导致崩溃。

如果我也添加@objc,则K_PreviewImage像这样的点击事件侦听器

 @objc func tapped(tap:UITapGestureRecognizer)
    {
        println("here")
        if(_touchCallback != nil)
        {
            touchCallback(self)
        }
    }

然后代码工作并触发触摸事件(内部K_PreviewImage和控制器回调函数'nestedTap'。

不知道为什么会这样,但确实如此。但是我仍然没有桨,因为当我创建K_PreviewImage一个函数变量而不是类成员变量时,我再次崩溃了

 override func viewDidLoad()
    {
        var image:iImage = iImage(imageName: "ja3.jpg")
        var k:K_PreviewImage = K_PreviewImage(image: image)
        k.touchCallback = nestedTap
        _view.addSubview(k.image)
    }

所以我的第一个问题是为什么我需要添加@objc以触发回调而不是给我一个不清楚的“释放”内存崩溃?

我的第二个问题是为什么当我将变量从成员变量移动到函数变量时会再次导致崩溃。如果对象被释放,它一开始就听不到点击事件,可以吗?为什么还会出现在荧幕上?为什么它只是因为它不是成员变量而被解除分配!

我怎么能动态地创建一个自定义对象并让它触发点击事件!

更新

这是完整的代码块,涉及如何使用触摸事件添加我的 K_PreviewImage

var _array:Array<iImage>!

    override func viewDidLoad()
    {
        _array = Array<iImage>()
        var image:iImage = iImage(imageName: "ja3.jpg")
        var k:K_PreviewImage = K_PreviewImage(image: image)
        k.touchCallback = nestedTap
        _view.addSubview(k.image)
        _array.append(k.image)
    }

    func nestedTap(k:K_PreviewImage)
    {
        println("Successs")
    }

解决了:

override func viewDidLoad()
    {
        _array = Array<K_PreviewImage>()
        var image:iImage = iImage(imageName: "ja3.jpg")
        var k:K_PreviewImage = K_PreviewImage(image: image)
        k.touchCallback = nestedTap
        _view.addSubview(k.image)
        _array.append(k)
    }

    func nestedTap(k:K_PreviewImage)
    {
        println("Successs")
    }

因为即使添加了子视图,我也没有存储对 K_PreviewImage 'k' 的引用,即使它属于 k,k 也没有被保留。通过使数组存储对 K_PreviewImage 而不是 iImage 的引用,编译器现在保留对 K_Preview Image 的引用

4

1 回答 1

3

首先,您似乎正在尝试将图像添加为子视图。我不太了解 Swift,但_view.addSubview(k.image)对我来说看起来不对,而且_view.addSubview(k).

其次,您没有保留对K_PreviewImage. 您正在分配k.image为子视图,这会导致k系统检测为“不再使用”。它会清理它,当你尝试访问它时,你会崩溃。

于 2014-10-17T18:05:57.913 回答