Слабое свойство для создания подкласса UIStackView в iOS Swift - PullRequest
0 голосов
/ 16 мая 2018

Я пытаюсь создать подкласс UIStackView и добавить некоторые элементы управления, которые мне нужны. Я добавляю UIView в качестве контейнера, и все другие представления, такие как UILabel, UIButton, UIImageView и т. Д., Будут добавлены в контейнер как подпредставление.

class UIButtonHeaderView: UIStackView {

    // MARK: - Properties

    var container: UIView!
    var titleLabel: UILabel!

    // MARK: - Initialization

    private func setUp() {
        // Set container.
        container = UIView()
        container.backgroundColor = .blue
        addArrangedSubview(container)

        // Set label.
        titleLabel = UILabel()
        container.addSubview(titleLabel)
        titleLabel.translatesAutoresizingMaskIntoConstraints = false
        titleLabel.leadingAnchor.constraint(equalTo: container.leadingAnchor).isActive = true
        titleLabel.bottomAnchor.constraint(equalTo: container.bottomAnchor).isActive = true
        titleLabel.trailingAnchor.constraint(lessThanOrEqualTo: container.trailingAnchor).isActive = true
        titleLabel.widthAnchor.constraint(greaterThanOrEqualToConstant: 0).isActive = true
        titleLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 0).isActive = true
        titleLabel.text = "This is just a simple test!!"
        titleLabel.backgroundColor = .green
        titleLabel.textColor = .red
        titleLabel.sizeToFit()
    }

    override init(frame: CGRect) {
        super.init(frame: frame)
        setUp()
    }

    required init(coder: NSCoder) {
        super.init(coder: coder)
        setUp()
    }
}

Код работает нормально, но у меня проблема при замене

var container: UIView!
var titleLabel: UILabel!

с

weak var container: UIView!
weak var titleLabel: UILabel!

Я думаю, что экземпляр класса UIButtonHeaderView и его свойство (container и titleLabel) могут иметь проблему с ссылочным циклом, поэтому я пытаюсь добавить слабый перед var, что вызывает сбой моего приложения.

Xcode сказал мне, что эта строка

container.backgroundColor = .blue

произошла ошибка с сообщением об ошибке

Thread 1: Fatal error: Unexpectedly found nil while unwrapping an Optional value

Кажется, что линия

container = UIView()

не удалось создать экземпляр класса UIView, поэтому контейнер имеет значение nil, что приводит к падению приложения, но я не знаю причину.

Ответы [ 3 ]

0 голосов
/ 16 мая 2018

Чтобы расширить ответ Хушбу, это:

weak var container: UIView!
weak var titleLabel: UILabel!

означает (через weak), что вы хотите, чтобы это значение стало nil, если объект отпущен, а также (через !)) что вы обещаете, что никогда не получите к нему доступ, если это nil.Это противоречиво.

0 голосов
/ 16 мая 2018

Чтобы расширить ответ Роба, у вас все еще будет проблема, если вы сделаете ваши свойства слабыми необязательными.

Когда вы говорите это:

container = UIView()

Нет строгих ссылок на вновь созданное представление, поэтому оно будет немедленно выпущено, и container станет nil, прежде чем вы сможете добавить его в представление стека.

Чтобы преодолеть эту проблему, вам нужно будет использовать локальную переменную для хранения ссылки UIView, пока она не будет добавлена ​​как подпредставление; в этот момент представление стека будет содержать сильную ссылку, и вы можете назначить ссылку для вашего свойства weak и позволить локальной переменной выйти из области видимости без освобождения представления.

let newContainer = UIView()
newContainer.backgroundColor = .blue
addArrangedSubview(newContainer)
container = newContainer

И я согласен с комментарием Роба; subclassinf UIStackView, вероятно, здесь не тот подход.

0 голосов
/ 16 мая 2018

Вы должны сделать опциональные, потому что когда у нас есть свойство, которое содержит слабую ссылку на объект, его тип должен быть опциональным, так как он может стать нулевым во время выполнения.

weak var container: UIView?
weak var titleLabel: UILabel?
...