英文:
How to add letters to an individual row in Swift
问题
I've translated the code portion as requested. Here it is:
struct CustomParent: View {
@StateObject var customViewModel = CustomViewModel()
let columnTexts = ["E", "A", "D", "G", "B", "E"] // << array
var body: some View {
VStack {
ForEach(0..<6, id: \.self) { rowIndex in
HStack(spacing: 10) {
Text(columnTexts[rowIndex])
ForEach(0..<10, id: \.self) { columnIndex in
let index = rowIndex * 10 + columnIndex
if index < customViewModel.childTexts.count {
CustomChild(index: index, customViewModel: customViewModel)
} else {
Spacer()
}
}
}
}
}
.frame(height: 20)
}
}
struct CustomChild: View {
let index: Int
@ObservedObject var customViewModel: CustomViewModel
var body: some View {
Button(action: {
customViewModel.showNumberInputAlert(for: index)
customViewModel.buttonPushed(at: index)
}) {
Text(customViewModel.childTexts[index])
.frame(width: 20, height: 2)
.foregroundColor(.black)
}
}
}
class CustomViewModel: ObservableObject {
@Published var childTexts = [String](repeating: "", count: 10)
@Published var fretSelected = false
func showNumberInputAlert(for rowIndex: Int) {
let alert = UIAlertController(title: "Enter a number", message: nil, preferredStyle: .alert)
alert.addTextField { textField in
textField.keyboardType = .numberPad
}
let doneAction = UIAlertAction(title: "Done", style: .default) { _ in
if let text = alert.textFields?.first?.text, let number = Int(text) {
// Make changes here to text
self.fretSelected = true
self.childTexts[rowIndex] = String(number)
}
}
alert.addAction(doneAction)
UIApplication.shared.windows.first?.rootViewController?.present(alert, animated: true, completion: nil)
}
init() {
for i in 0..<childTexts.count {
if fretSelected {
childTexts[i]
}
else{
childTexts[i] = "__"
}
}
}
}
Please note that I've replaced the HTML-encoded characters (e.g., "
) with their actual representations in the code.
英文:
I'm attempting to create 6 rows of 10 columns, with a individual letter attached to each row. In my particular case I want the first letter for the array to display, then the next and so on. As of now, only the first letter displays.
I'm not sure how to increment the column texts in the view itself to display a new letter for each row.
I attached an image below of the issue of what currently is happening.
struct CustomParent: View {
@StateObject var customViewModel = CustomViewModel()
let columnTexts = ["E", "A", "D", "G", "B", "E"] // << array
var body: some View {
VStack {
ForEach(0..<6, id: \.self) { rowIndex in
HStack(spacing: 10) {
Text(columnTexts[rowIndex])
ForEach(0..<10, id: \.self) { columnIndex in
let index = rowIndex * 10 + columnIndex
if index < customViewModel.childTexts.count {
CustomChild(index: index, customViewModel: customViewModel)
} else {
Spacer()
}
}
}
}
}
.frame(height: 20)
}
}
struct CustomChild: View {
let index: Int
@ObservedObject var customViewModel: CustomViewModel
var body: some View {
Button(action: {
customViewModel.showNumberInputAlert(for: index)
customViewModel.buttonPushed(at: index)
}) {
Text(customViewModel.childTexts[index])
.frame(width: 20, height: 2)
.foregroundColor(.black)
// .border(.black)
}
}
}
class CustomViewModel: ObservableObject {
@Published var childTexts = [String](repeating: "", count: 10)
@Published var fretSelected = false
func showNumberInputAlert(for rowIndex: Int) {
let alert = UIAlertController(title: "Enter a number", message: nil, preferredStyle: .alert)
alert.addTextField { textField in
textField.keyboardType = .numberPad
}
let doneAction = UIAlertAction(title: "Done", style: .default) { _ in
if let text = alert.textFields?.first?.text, let number = Int(text) {
// Make changes here to text
self.fretSelected = true
self.childTexts[rowIndex] = String(number)
}
}
alert.addAction(doneAction)
UIApplication.shared.windows.first?.rootViewController?.present(alert, animated: true, completion: nil)
}
init() {
for i in 0..<childTexts.count {
if fretSelected {
childTexts[i]
}
else{
childTexts[i] = "__"
}
}
}
答案1
得分: 1
Here is the translated code:
一件事情:
let index = rowIndex * 10 + columnIndex
if index < customViewModel.childTexts.count {
CustomChild(index: index, customViewModel: customViewModel)
} else {
Spacer()
}
如果我理解代码正确,我们将无法显示第二行的自定义子项,因为索引将高于childTexts.count,您确定您发布的代码与屏幕一致吗?
第二件事,它会崩溃,因为您将“index”传递给childView,但在childView中引用了一个包含10个元素的数组
//在CustomChild中:
Text(customViewModel.childTexts[index]) //第二行将给出索引20,导致越界
使用一个函数来保留“index”的最后一个数字将非常有用,以避免越界并在childView中保留真正的索引 https://stackoverflow.com/questions/30415937/how-to-split-an-int-to-its-individual-digits
第三,在您发布的代码上进行了微小的修复后,我得到了您正在寻找的显示效果。
//请用以下内容替换
if index < customViewModel.childTexts.count {
//与
if columnIndex < customViewModel.childTexts.count {
//在CustomChild中
Text(customViewModel.childTexts[index])
//与
Text(customViewModel.childTexts[index.lastDigit]) //lastDigit将是我上面链接的StackOverflow资源中的一个函数
对于lastDigit函数,像这样的东西应该可以胜任:
```swift
extension Int {
var lastDigit: Int {
String(self).last!.wholeNumberValue!
}
}
用法:
let index = 156
print(index.lastDigit) //应该打印6
print(-4577.lastDigit) //应该打印-7
print(abs(-88).lastDigit) //应该打印8
注意:我强制解包,因为函数last
和wholeNumberValue
在非可选Int上不能失败(如果您想使用可选Int进行操作,我会让您添加一些nil检查)。
<details>
<summary>英文:</summary>
one thing :
let index = rowIndex * 10 + columnIndex
if index < customViewModel.childTexts.count {
CustomChild(index: index, customViewModel: customViewModel)
} else {
Spacer()
If I understand the code well we would not be able to display the customs childs of the second row as the index would be higher that the childTexts.count, are you sure the code you posted is accurate with the screen you posted?
Second thing, it would crash as you are giving "index" to childView but in the childView you are referencing an array of 10 elements
//In CustomChild:
Text(customViewModel.childTexts[index]) //second row would give index 20 that cause outOfRange
Using a function to keep only the last digit of the "index" would be useful to avoid outOfRange and keep the real index in your childView https://stackoverflow.com/questions/30415937/how-to-split-an-int-to-its-individual-digits
Third, after a minor fix on the code you posted I have the display you're seeking for.
// Please replace
if index < customViewModel.childTexts.count {
//with
if columnIndex < customViewModel.childTexts.count {
//In CustomChild
Text(customViewModel.childTexts[index])
//with
Text(customViewModel.childTexts[index.lastDigit]) //lastDigit would be a function from the StackOverlow resource I linked above
The edits I stated above are the only one I made to your code for it to obtain the result I'll post under:
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/IpXNv.png
EDIT: Something like this should do the job for the lastDigit function
extension Int {
var lastDigit: Int {
String(self).last!.wholeNumberValue!
}
}
usage:
let index = 156
print(index.lastDigit) // should print 6
print(-4577.lastDigit) // should print -7
print(abs(-88).lastDigit) // should print 8
Note: I force unwrap as the functions `last` and `wholeNumberValue` cannot fail on a non-optionnal Int (if you want to work with optional Int I let you add some nil checking.)
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论