Когда я должен использовать “финал”?

Вы, безусловно, можете сделать это с помощью прокрутки и просмотра стека.

Ваша основная проблема заключалась в том, что вы создаете свою «деталь» вне цикла for:

    // this creates ONE part view
    let part = createPart()
    // your loop simply adds and re-adds that one part view
    for i in 0..<numOfViewsNeeded {
        view.addSubview(part)
        stackView.addArrangedSubview(part)
    }

Она должна выглядеть следующим образом:

    for i in 0..<numOfViewsNeeded {
        // create a new part view
        let part = createPart()
        // add that new view to the stack view
        stackView.addArrangedSubview(part)
    }
[118 ] Вот модифицированная версия вашего кода, которая даст вам желаемый результат:

class AddStuffViewController: UIViewController {

    var numOfViewsNeeded = 5

    var bkgColors: [UIColor] = [
        .blue,
        .green,
        .red,
        .orange,
        .yellow
    ]

    func createPart(_ n: Int) -> UIView {
        let part = UIView()
        part.translatesAutoresizingMaskIntoConstraints  = false
        part.layer.cornerRadius = 4
        part.layer.masksToBounds = true
        part.backgroundColor = bkgColors[n] // .random()
        part.heightAnchor.constraint(equalToConstant: 300).isActive = true

        let partLabel1 = UILabel(frame: CGRect(x:10, y: 0, width: 300, height: 50))
        let partLabel2 = UILabel(frame: CGRect(x:10, y: 35, width: 300, height: 50))
        let partLabel3 = UILabel(frame: CGRect(x:10, y: 75, width: 300, height: 50))
        let partLabel4 = UILabel(frame: CGRect(x:10, y: 115, width: 300, height: 50))
        let partLabel5 = UILabel(frame: CGRect(x:10, y: 155, width: 300, height: 50))
        let partLabel6 = UILabel(frame: CGRect(x:10, y: 195, width: 300, height: 50))
        partLabel1.text = "NO."
        partLabel1.textColor = .white
        partLabel2.text = "Code"
        partLabel2.textColor = .white
        partLabel3.text = "Br"
        partLabel3.textColor = .white
        partLabel4.text = "Stat"
        partLabel4.textColor = .white
        partLabel5.text = "Line"
        partLabel5.textColor = .white
        partLabel6.text = "B"
        partLabel6.textColor = .white

        part.addSubview(partLabel1)
        part.addSubview(partLabel2)
        part.addSubview(partLabel3)
        part.addSubview(partLabel4)
        part.addSubview(partLabel5)
        part.addSubview(partLabel6)

        return part
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        view.addSubview(containerScrollView)
        containerScrollView.addSubview(contentView)
        contentView.addSubview(stackMainView)

        for i in 0..<numOfViewsNeeded {
            let part = createPart(i)
            stackMainView.addArrangedSubview(part)
        }

        contentView.topAnchor.constraint(equalTo: self.containerScrollView.topAnchor, constant: 0).isActive = true
        contentView.leadingAnchor.constraint(equalTo: self.containerScrollView.leadingAnchor, constant: 0).isActive = true
        contentView.trailingAnchor.constraint(equalTo:self.containerScrollView.trailingAnchor, constant: 0).isActive = true
        contentView.bottomAnchor.constraint(equalTo: self.containerScrollView.bottomAnchor, constant: 0).isActive = true

        contentView.widthAnchor.constraint(equalTo:self.containerScrollView.widthAnchor, constant: 0).isActive = true

        containerScrollView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 0).isActive = true
        containerScrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0).isActive = true
        containerScrollView.trailingAnchor.constraint(equalTo:self.view.trailingAnchor, constant: 0).isActive = true
        containerScrollView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true

        stackMainView.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 50).isActive = true
        stackMainView.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 8).isActive = true
        stackMainView.trailingAnchor.constraint(equalTo: self.contentView.trailingAnchor, constant: -8).isActive = true
        stackMainView.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -30).isActive = true


    }

    override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        print(stackMainView.arrangedSubviews.count)
    }

    var containerScrollView: UIScrollView = {
        let scrollView = UIScrollView()
        scrollView.translatesAutoresizingMaskIntoConstraints  = false
        scrollView.backgroundColor = .gray
        scrollView.isScrollEnabled = true
        return scrollView
    }()

    var contentView: UIView = {
        let view = UIView()
        view.translatesAutoresizingMaskIntoConstraints  = false
        view.backgroundColor = .cyan
        return view
    }()
    let stackMainView: UIStackView = {
        let stackView = UIStackView()
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.axis = .vertical
        return stackView

    }()
}

Примечание: если вы считаете, что вам может понадобиться партий деталей, вы, вероятно, лучше отключить использование табличного представления и спроектировать «деталь» как ячейку многократного использования.

12
задан Charles 23 December 2012 в 21:36
поделиться

6 ответов

Это препятствует тому, чтобы другие программисты делали материал с Вашими классами, которые Вы не предназначаете, чтобы они сделали. Так вместо того, чтобы делать высказывание комментария "не используют этот класс, чтобы сделать XXX", можно разработать его таким способом, которым они не испытают желание переопределить его и злоупотребить им тем способом.

Править: Так как пример требуют, я опишу случай, где Вы могли бы найти, что это ключевое слово, удобное..., говорит, что у Вас есть класс, который определяет, как два объекта могут общаться друг с другом, скажем, слушателя и notifier. Класс слушателя должен, очевидно, позволить наследование, но Вы могли бы хотеть сделать notifier финал класса так, чтобы это использовалось в, "имеет -" отношения. Таким образом, можно сделать некоторые предположения из объектов прослушивателя о природе сообщений, которые они получают.

Иначе было бы возможно наследоваться тому классу, сделать, всем видам сумасшедшего материала нравится, расширяют сообщения и так далее. Если Вы не хотите, чтобы другие программисты сделали это, то Вы могли сделать финал класса. Кроме того, это могло бы иметь намного больше смысла в широко используемом общедоступном API, поскольку он также позволяет другим программистам с готовностью понимать, который классы в порядке для разделения на подклассы.

Другой пример - говорит, что у Вас есть основанный на буфере потоковый процессор, и в Вашем чтении () / запись () метод, Вы поддерживаете некоторые данные о текущем состоянии Вашего объекта (т.е., текущий байт или безотносительно). Нет никакого способа гарантировать, что любой разделяющий этот класс на подклассы назвал бы методы super во время обработки - и так как такой класс, вероятно, только содержит несколько методов, лучше просто сделать все это финалом вместо каждого метода. Это снова вынуждает людей, использующих класс для, "имеет -", не "-", и таким образом, может управлять, как Вы ожидаете, что код будет выполнен.

Я согласился бы с Вами в том создании всего финала класса, вероятно, что-то, что необходимо было бы сделать очень редко, но хорошо, что PHP имеет эту возможность, должен Вы принимать решение осуществить его.

12
ответ дан 2 December 2019 в 06:45
поделиться

"Осуществите Состав по Наследованию", помещает его скорее кратко. Вы гарантируете определенное поведение своего класса, в который ничто иное не может вмешаться, который, как следующий раздел объясняет, может обладать преимуществами безопасности также.

6
ответ дан 2 December 2019 в 06:45
поделиться

Некоторые люди утверждают, что необходимо объявить весь финал классов, если Вы конкретно не намереваетесь позволить и исследовали последствия, полиморфное расширение его. Я склонен чувствовать, что это подразумевает большое недоверие к тому, кто бы ни еще работает с Вашим кодом, но к сожалению, иногда это гарантировано.

3
ответ дан 2 December 2019 в 06:45
поделиться

На многих языках объявляя класс, поскольку финал также предоставляет преимущества оптимизации, так как он не должен смотреть на virt таблицу для методов.

Если Вы хотите осуществить намерение класса, и намерение таково, что не имеет смысла разделять на подклассы, то используйте финал; иначе нет никакого значительного преимущества.

В целом это - просто механизм для осуществления намерения.

2
ответ дан 2 December 2019 в 06:45
поделиться

Заключительный класс является классом, который не может быть разделен на подклассы, таким образом, что-либо, из чего Вы не хотите создавать производные. Например, в Java, Математический класс является окончательным, так как Java не хочет, чтобы Вы смогли переопределить то, что означает Абсолютное значение.

0
ответ дан 2 December 2019 в 06:45
поделиться

финал (и впаянный c#) мог использоваться (разработчиками библиотеки классов) для осуществления некоторого основного поведения класса.
Например, осуществите это, строка имеет неизменное поведение
Строковый класс в Java отмечен финал, и в c# он отмечен изолированный.
Все строки неизменны, и то поведение не может быть изменено.

0
ответ дан 2 December 2019 в 06:45
поделиться
Другие вопросы по тегам:

Похожие вопросы: