创建一个函数以在 Swift4 中从字符串数组以编程方式创建 UILabel
Creating a function to programmatically create UILabels from a String Array in Swift4
我能够以编程方式创建一个 UILabel
,但是当我创建一个函数时,我是否必须将它放在 viewDidLoad()
方法中?我需要使用 self.view.addSubview(label)
将标签附加到视图,但它会引发错误,然后当它位于 viewDidLoad()
.
之外时,我的构建就会失败
每当我尝试在 viewDidLoad
方法之外创建函数时,它都会显示 "use of unresolved identifier self"。有没有办法解决?
此外,当我将函数放在 viewDidLoad
中时,一切正常,并且创建了标签,但它们是在彼此之上创建的。如果可能的话,我希望标签彼此相邻?
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func createALabel(inputtedString: String) -> Void {
let string = inputtedString
let test = string.components(separatedBy: " ")
for element in test {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 60, height: 35))
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
label.textColor = UIColor.blue
label.text = element
label.layer.borderColor = UIColor.blue.cgColor
label.layer.borderWidth = 3.0
self.view.addSubview(label)
}
}
}
Even with the position change my labels are still stacking
您必须添加一个整数变量来设置 x 位置。这里我根据设置的x位置设置了xPos变量
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func createALabel(inputtedString: String) -> Void {
let string = inputtedString
let test = string.components(separatedBy: " ")
let xPos = 0
for element in test {
let label = UILabel(frame: CGRect(x: xPos, y: 0, width: 60, height: 35))
// label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
xPos = xPos + 60 + 10 // Update xPos width 60 & 10 is gap between two label
label.textColor = UIColor.blue
label.text = element
label.layer.borderColor = UIColor.blue.cgColor
label.layer.borderWidth = 3.0
self.view.addSubview(label)
}
}
}
管理此类几何图形 UIStackView
可能会有用。
你也不需要在 viewDidLoad 中调用这个方法,loadView 生命周期方法更适合这个,当你想要初始化和管理你的视图时
以编程方式。
class ViewController: UIViewController {
private let vstackView = UIStackView()
private let horizontal_spacing = 20.0
private let spaceConstantForLetter = 10.0
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
vstackView.axis = .vertical
vstackView.translatesAutoresizingMaskIntoConstraints = false
vstackView.alignment = .center
vstackView.spacing = 10
self.view.addSubview(vstackView)
vstackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
vstackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
createALabel(inputtedString: "this is a long test string that exceeds screen width")//
// Do any additional setup after loading the view.
}
func createALabel(inputtedString: String) -> Void {
let string = inputtedString
let test = string.components(separatedBy: " ")
var horizontalStackList = [UILabel] ()
for (index, element) in test.enumerated() {
let label = UILabel()
label.textAlignment = .center
label.textColor = UIColor.blue
label.text = element
label.layer.borderColor = UIColor.blue.cgColor
label.layer.borderWidth = 1.0
horizontalStackList.append(label)
let totalLetterNumber = horizontalStackList.map { [=10=].text!.count }.reduce(0, +)
let contentWidth = Double(totalLetterNumber) * spaceConstantForLetter //constant for a letter that takes how much space from screen
let spacingWidth = Double(horizontalStackList.count - 1) * horizontal_spacing
/*add left and right margins if exist*/
if((CGFloat(spacingWidth + contentWidth) > UIScreen.main.bounds.width) || index == test.count - 1) {
let exceedingLabel = horizontalStackList.popLast()
let hstackView = UIStackView(arrangedSubviews: horizontalStackList)
hstackView.axis = .horizontal
hstackView.translatesAutoresizingMaskIntoConstraints = false
hstackView.spacing = CGFloat(horizontal_spacing)
hstackView.alignment = .center
vstackView.addArrangedSubview(hstackView)
horizontalStackList.removeAll(keepingCapacity: false)
horizontalStackList.append(exceedingLabel!)
}
}
}
}
编辑:添加了 Jazzin 想要的自动换行
使用集合视图是最佳选择。它使您的工作更轻松。试试这个
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
var wordsArr = [String]()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
collectionView.backgroundColor = .white
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(WordCell.self, forCellWithReuseIdentifier: "WordCell")
collectionView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(collectionView)
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(5)-[collectionView]-(5)-|", options: [], metrics: nil, views: ["collectionView":collectionView]))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(5)-[collectionView]-(5)-|", options: [], metrics: nil, views: ["collectionView":collectionView]))
createALabel(inputtedString: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam")
}
func createALabel(inputtedString: String) -> Void {
wordsArr = inputtedString.components(separatedBy: " ")
collectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return wordsArr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "WordCell", for: indexPath) as? WordCell ?? WordCell()
cell.label.text = wordsArr[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = (wordsArr[indexPath.row] as NSString).boundingRect(with: CGSize.zero, options: .usesLineFragmentOrigin, attributes: [.font: UIFont.systemFont(ofSize: 16.0)], context: nil).size.width
let size = CGSize(width: width + 10
, height: 35)
return size
}
}
class WordCell: UICollectionViewCell {
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() {
backgroundColor = .white
label.font = UIFont.systemFont(ofSize: 16.0)
label.textAlignment = .center
label.textColor = UIColor.blue
label.layer.borderColor = UIColor.blue.cgColor
label.layer.borderWidth = 3.0
label.translatesAutoresizingMaskIntoConstraints = false
addSubview(label)
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[label(35)]|", options: [], metrics: nil, views: ["label":label]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[label]|", options: [], metrics: nil, views: ["label":label]))
}
}
我能够以编程方式创建一个 UILabel
,但是当我创建一个函数时,我是否必须将它放在 viewDidLoad()
方法中?我需要使用 self.view.addSubview(label)
将标签附加到视图,但它会引发错误,然后当它位于 viewDidLoad()
.
每当我尝试在 viewDidLoad
方法之外创建函数时,它都会显示 "use of unresolved identifier self"。有没有办法解决?
此外,当我将函数放在 viewDidLoad
中时,一切正常,并且创建了标签,但它们是在彼此之上创建的。如果可能的话,我希望标签彼此相邻?
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func createALabel(inputtedString: String) -> Void {
let string = inputtedString
let test = string.components(separatedBy: " ")
for element in test {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 60, height: 35))
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
label.textColor = UIColor.blue
label.text = element
label.layer.borderColor = UIColor.blue.cgColor
label.layer.borderWidth = 3.0
self.view.addSubview(label)
}
}
}
Even with the position change my labels are still stacking
您必须添加一个整数变量来设置 x 位置。这里我根据设置的x位置设置了xPos变量
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
func createALabel(inputtedString: String) -> Void {
let string = inputtedString
let test = string.components(separatedBy: " ")
let xPos = 0
for element in test {
let label = UILabel(frame: CGRect(x: xPos, y: 0, width: 60, height: 35))
// label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
xPos = xPos + 60 + 10 // Update xPos width 60 & 10 is gap between two label
label.textColor = UIColor.blue
label.text = element
label.layer.borderColor = UIColor.blue.cgColor
label.layer.borderWidth = 3.0
self.view.addSubview(label)
}
}
}
管理此类几何图形 UIStackView
可能会有用。
你也不需要在 viewDidLoad 中调用这个方法,loadView 生命周期方法更适合这个,当你想要初始化和管理你的视图时
以编程方式。
class ViewController: UIViewController {
private let vstackView = UIStackView()
private let horizontal_spacing = 20.0
private let spaceConstantForLetter = 10.0
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
vstackView.axis = .vertical
vstackView.translatesAutoresizingMaskIntoConstraints = false
vstackView.alignment = .center
vstackView.spacing = 10
self.view.addSubview(vstackView)
vstackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
vstackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
createALabel(inputtedString: "this is a long test string that exceeds screen width")//
// Do any additional setup after loading the view.
}
func createALabel(inputtedString: String) -> Void {
let string = inputtedString
let test = string.components(separatedBy: " ")
var horizontalStackList = [UILabel] ()
for (index, element) in test.enumerated() {
let label = UILabel()
label.textAlignment = .center
label.textColor = UIColor.blue
label.text = element
label.layer.borderColor = UIColor.blue.cgColor
label.layer.borderWidth = 1.0
horizontalStackList.append(label)
let totalLetterNumber = horizontalStackList.map { [=10=].text!.count }.reduce(0, +)
let contentWidth = Double(totalLetterNumber) * spaceConstantForLetter //constant for a letter that takes how much space from screen
let spacingWidth = Double(horizontalStackList.count - 1) * horizontal_spacing
/*add left and right margins if exist*/
if((CGFloat(spacingWidth + contentWidth) > UIScreen.main.bounds.width) || index == test.count - 1) {
let exceedingLabel = horizontalStackList.popLast()
let hstackView = UIStackView(arrangedSubviews: horizontalStackList)
hstackView.axis = .horizontal
hstackView.translatesAutoresizingMaskIntoConstraints = false
hstackView.spacing = CGFloat(horizontal_spacing)
hstackView.alignment = .center
vstackView.addArrangedSubview(hstackView)
horizontalStackList.removeAll(keepingCapacity: false)
horizontalStackList.append(exceedingLabel!)
}
}
}
}
编辑:添加了 Jazzin 想要的自动换行
使用集合视图是最佳选择。它使您的工作更轻松。试试这个
class ViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
var wordsArr = [String]()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
collectionView.backgroundColor = .white
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(WordCell.self, forCellWithReuseIdentifier: "WordCell")
collectionView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(collectionView)
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-(5)-[collectionView]-(5)-|", options: [], metrics: nil, views: ["collectionView":collectionView]))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-(5)-[collectionView]-(5)-|", options: [], metrics: nil, views: ["collectionView":collectionView]))
createALabel(inputtedString: "Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam")
}
func createALabel(inputtedString: String) -> Void {
wordsArr = inputtedString.components(separatedBy: " ")
collectionView.reloadData()
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return wordsArr.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "WordCell", for: indexPath) as? WordCell ?? WordCell()
cell.label.text = wordsArr[indexPath.row]
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let width = (wordsArr[indexPath.row] as NSString).boundingRect(with: CGSize.zero, options: .usesLineFragmentOrigin, attributes: [.font: UIFont.systemFont(ofSize: 16.0)], context: nil).size.width
let size = CGSize(width: width + 10
, height: 35)
return size
}
}
class WordCell: UICollectionViewCell {
let label = UILabel()
override init(frame: CGRect) {
super.init(frame: frame)
commonInit()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
func commonInit() {
backgroundColor = .white
label.font = UIFont.systemFont(ofSize: 16.0)
label.textAlignment = .center
label.textColor = UIColor.blue
label.layer.borderColor = UIColor.blue.cgColor
label.layer.borderWidth = 3.0
label.translatesAutoresizingMaskIntoConstraints = false
addSubview(label)
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[label(35)]|", options: [], metrics: nil, views: ["label":label]))
addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[label]|", options: [], metrics: nil, views: ["label":label]))
}
}