我对学习Swift还是很陌生,并且有一个框架可以在其中均匀显示字母。
我有3个for循环,其中字母A-X在4行中显示6列,而Y和Z在2-3列的第5行中显示(因此居中)。但是,要实现这一点,我必须复制代码。有没有更好的方法可以解决此问题,所以我不必重复代码?
let allLetters = (65...90).map { Character(Unicode.Scalar($0)) }
let width = 80
let height = 80
for row in 0..<4 {
for col in 0..<6 {
let letterButton = UIButton(type: .system)
letterButton.titleLabel?.font = UIFont.systemFont(ofSize: 36)
letterButton.addTarget(self, action: #selector(letterTapped), for: .touchUpInside)
let frame = CGRect(x: col * width, y: row * height, width: width, height: height)
letterButton.frame = frame
buttonsView.addSubview(letterButton)
letterButtons.append(letterButton)
}
}
for col in 2..<4 {
let letterButton = UIButton(type: .system)
letterButton.titleLabel?.font = UIFont.systemFont(ofSize: 36)
letterButton.addTarget(self, action: #selector(letterTapped), for: .touchUpInside)
let frame = CGRect(x: col * width, y: 4 * height, width: width, height: height)
letterButton.frame = frame
buttonsView.addSubview(letterButton)
letterButtons.append(letterButton)
}
for (index, button) in letterButtons.enumerated() {
button.setTitle(String(allLetters[index]), for: .normal)
}
}
答案 0 :(得分:0)
您可以简化和提高性能,删除两个for循环,如下所示:
let allLetters = (65...90).map { Character(Unicode.Scalar($0)) }
let width = 80
let height = 80
var letterIndex = 0
let lastRowIndex = 4
let defaultRowColumnRange = 0..<6
let lastRowColumnRange = 2..<4
for row in 0...lastRowIndex {
let rangeForRow = row == lastRowIndex ? lastRowColumnRange : defaultRowColumnRange
for col in rangeForRow {
let letterButton = UIButton(type: .system)
letterButton.titleLabel?.font = UIFont.systemFont(ofSize: 36)
letterButton.addTarget(self, action: #selector(letterTapped), for: .touchUpInside)
if allLetters.count > letterIndex {
letterButton.setTitle(String(allLetters[letterIndex]), for: .normal)
letterIndex += 1
}
let frame = CGRect(x: col * width, y: row * height, width: width, height: height)
letterButton.frame = frame
view.addSubview(letterButton)
letterButtons.append(letterButton) // Might not be necessary anymore
}
}
答案 1 :(得分:0)
首先,我仍将所有按钮操作移至其自身的功能中:
func addButton(letter: Character, x: Int, y: Int) {
let letterButton = UIButton(type: .system)
letterButton.setTitle(String(letter), for: .normal)
letterButton.titleLabel?.font = UIFont.systemFont(ofSize: 36)
letterButton.addTarget(self, action: #selector(letterTapped), for: .touchUpInside)
let frame = CGRect(x: x, y: y, width: width, height: height)
letterButton.frame = frame
buttonsView.addSubview(letterButton)
letterButtons.append(letterButton)
}
因为这为所有ui操作提供了很好的隔离。即使使用此功能替换了重复的代码,您也得到了改善。
但也要假设
let numberOfLettersPerRow = 6
您知道每行有多少个按钮:
let buttonsInCurrentRow = min(numberOfLettersPerRow, allLetters.count - row * numberOfLettersPerRow) // i.e. 6 or less
因此,您可以决定按钮是背靠背还是在按钮前后都有空白:
let gap = (numberOfLettersPerRow - buttonsInCurrentRow) * width / 2
对于numberOfLettersPerRow == buttonsInCurrentRow
行,该间隙将为0,而对于numberOfLettersPerRow < buttonsInCurrentRow
行,该间隙将大于0,我们希望该间隙为总间隙的一半(因此,前面有相等的空间并返回)
所以现在您将按钮放置如下:
let frame = CGRect(x: gap + col * width, y: row * height, width: width, height: height)
然后在您拥有的按钮上而不是在行和列上运行循环。为什么?因为如果明天您改变主意如何放置按钮,则无需更改很多代码:
for i in 0...allLetters.count - 1 {
let row = Int(i / numberOfLettersPerRow)
let col = i % numberOfLettersPerRow
let buttonsInCurrentRow = min(numberOfLettersPerRow, allLetters.count - row * numberOfLettersPerRow)
let gap = (numberOfLettersPerRow - buttonsInCurrentRow) * width / 2
addButton(letter: allLetters[i], x: gap + col * width, y: row * height)
}
就是这样。