UITapGestureRecognizer, вызывающий сбой при различных сообщениях об ошибках

У меня есть серьезная проблема, с которой я застрял на работе и ДЕЙСТВИТЕЛЬНО буду признателен за помощь. Это стоило мне уже 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

1 ответ

Решение

Во-первых, похоже, что вы пытаетесь добавить изображение в качестве подпредставления. Я не очень хорошо знаю Свифта, но _view.addSubview(k.image) выглядит неправильно для меня и будет иметь больше смысла, как _view.addSubview(k),

Во-вторых, вы не держите ссылку на свой K_PreviewImage, Вы назначаете k.image как подпредставление, которое вызывает k быть обнаруженным системой как "больше не используемая". Это очистит его, и когда вы попытаетесь получить к нему доступ, вы потерпите крах.

Другие вопросы по тегам