Вы, безусловно, можете сделать это с помощью прокрутки и просмотра стека.
Ваша основная проблема заключалась в том, что вы создаете свою «деталь» вне цикла 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
}()
}
Примечание: если вы считаете, что вам может понадобиться партий деталей, вы, вероятно, лучше отключить использование табличного представления и спроектировать «деталь» как ячейку многократного использования.
Это препятствует тому, чтобы другие программисты делали материал с Вашими классами, которые Вы не предназначаете, чтобы они сделали. Так вместо того, чтобы делать высказывание комментария "не используют этот класс, чтобы сделать XXX", можно разработать его таким способом, которым они не испытают желание переопределить его и злоупотребить им тем способом.
Править: Так как пример требуют, я опишу случай, где Вы могли бы найти, что это ключевое слово, удобное..., говорит, что у Вас есть класс, который определяет, как два объекта могут общаться друг с другом, скажем, слушателя и notifier. Класс слушателя должен, очевидно, позволить наследование, но Вы могли бы хотеть сделать notifier финал класса так, чтобы это использовалось в, "имеет -" отношения. Таким образом, можно сделать некоторые предположения из объектов прослушивателя о природе сообщений, которые они получают.
Иначе было бы возможно наследоваться тому классу, сделать, всем видам сумасшедшего материала нравится, расширяют сообщения и так далее. Если Вы не хотите, чтобы другие программисты сделали это, то Вы могли сделать финал класса. Кроме того, это могло бы иметь намного больше смысла в широко используемом общедоступном API, поскольку он также позволяет другим программистам с готовностью понимать, который классы в порядке для разделения на подклассы.
Другой пример - говорит, что у Вас есть основанный на буфере потоковый процессор, и в Вашем чтении () / запись () метод, Вы поддерживаете некоторые данные о текущем состоянии Вашего объекта (т.е., текущий байт или безотносительно). Нет никакого способа гарантировать, что любой разделяющий этот класс на подклассы назвал бы методы super во время обработки - и так как такой класс, вероятно, только содержит несколько методов, лучше просто сделать все это финалом вместо каждого метода. Это снова вынуждает людей, использующих класс для, "имеет -", не "-", и таким образом, может управлять, как Вы ожидаете, что код будет выполнен.
Я согласился бы с Вами в том создании всего финала класса, вероятно, что-то, что необходимо было бы сделать очень редко, но хорошо, что PHP имеет эту возможность, должен Вы принимать решение осуществить его.
"Осуществите Состав по Наследованию", помещает его скорее кратко. Вы гарантируете определенное поведение своего класса, в который ничто иное не может вмешаться, который, как следующий раздел объясняет, может обладать преимуществами безопасности также.
Некоторые люди утверждают, что необходимо объявить весь финал классов, если Вы конкретно не намереваетесь позволить и исследовали последствия, полиморфное расширение его. Я склонен чувствовать, что это подразумевает большое недоверие к тому, кто бы ни еще работает с Вашим кодом, но к сожалению, иногда это гарантировано.
На многих языках объявляя класс, поскольку финал также предоставляет преимущества оптимизации, так как он не должен смотреть на virt таблицу для методов.
Если Вы хотите осуществить намерение класса, и намерение таково, что не имеет смысла разделять на подклассы, то используйте финал; иначе нет никакого значительного преимущества.
В целом это - просто механизм для осуществления намерения.
Заключительный класс является классом, который не может быть разделен на подклассы, таким образом, что-либо, из чего Вы не хотите создавать производные. Например, в Java, Математический класс является окончательным, так как Java не хочет, чтобы Вы смогли переопределить то, что означает Абсолютное значение.
финал (и впаянный c#) мог использоваться (разработчиками библиотеки классов) для осуществления некоторого основного поведения класса.
Например, осуществите это, строка имеет неизменное поведение
Строковый класс в Java отмечен финал, и в c# он отмечен изолированный.
Все строки неизменны, и то поведение не может быть изменено.