按顺序显示数组中的每个元素

Displaying each element in an array in sequence

提问人:MarkB 提问时间:11/17/2023 最后编辑:HangarRashMarkB 更新时间:11/17/2023 访问量:41

问:

我正在尝试显示文本数组的每个成员几秒钟。我编写的代码始终显示最后一个成员。这应该如何解决?

import SwiftUI

class ViewController: UIViewController {

    var connectedView: UIView?
    var emotionView: UIView?
    var labelsButton = UIButton(type: .roundedRect)
              
    let labels = ["Apple", "Baby", "Cat", "Dog", "Evening", "Friend", "Go", "Happy", "Independent", "Joyful"]
   
    override func viewDidLoad() {
        super.viewDidLoad()
        layoutForConnected()
    }
  
    @objc func didTouchlabelButton(_ sender: UIButton?) {
        sender?.setTitle("Labels", for: .normal)
        layoutForCharacter()
    }
          
    func layoutForConnected() {
        if connectedView == nil {
            connectedView = UIView(frame: view.bounds)
            connectedView?.backgroundColor = UIColor.white
            
            labelsButton.frame = CGRect(x: 70, y: 475, width: 180, height: 60)
            labelsButton.setTitle("Labels", for: .normal)
            labelsButton.addTarget(self,action:
                                        #selector(didTouchlabelButton),for: .touchUpInside)
            labelsButton.tintColor = UIColor.black
            labelsButton.backgroundColor = UIColor.init(hue: 0.563, saturation: 1.0, brightness: 0.93, alpha: 1.0)
            labelsButton.layer.cornerRadius = 20
            connectedView?.addSubview(labelsButton)
        }
        
        if let connectedView = connectedView {
            self.view.addSubview(connectedView)
        }
    }
    
    var displayTime = 5.0
    var index = 0
       
    func layoutForCharacter() {
                
        // set up frame and background color
        emotionView = UIView(frame: view.bounds)
        emotionView?.backgroundColor = UIColor.init(hue: 0.563, saturation: 1.0, brightness: 0.93, alpha: 1.0)
        
        let labelLabel = UILabel(frame: CGRect(x: 0, y: 400 , width: view.frame.size.width, height: 20))
        labelLabel.textAlignment = .center
        
        // Display each label for displayTime seconds
               index = 0
        
        view?.addSubview(labelLabel)
        labelLabel.text = labels[index]
        
        while index < 9
        {
          labelLabel.text = labels[index] // Displays "Joyful", i.e. index = 9
            
            DispatchQueue.main.asyncAfter(deadline: .now() + displayTime * Double(index))
            {  [self] in
                labelLabel.text = labels[index]
            }
            self.index += 1
        }
        DispatchQueue.main.asyncAfter(deadline: .now() + displayTime * Double(index))
        {  [self] in
            self.layoutForConnected()
        }
    }
}

我已经更改了位置,但这并没有纠正问题。DispatchQueue.main.asyncAfter

阵列 快速 延迟 显示

评论

0赞 HangarRash 11/17/2023
不相关,但你为什么要导入而不是?SwiftUIUIKit
1赞 HangarRash 11/17/2023
主要问题是你在循环中调用了两次。删除第一个。labelLabel.text = labels[index]while

答:

0赞 son 11/17/2023 #1

我认为你可以用递归的方式重写它。它很容易阅读。

func layoutForCharacter() {
    ...
    recursiveShowUpEmotion(label: labelLabel, index: index)
}

private func recursiveShowUpEmotion(label: UILabel, index: Int) {
    guard index < 9 else {
        layoutForConnected()
        return
    }
    label.text = labels[index]
    
    DispatchQueue.main.asyncAfter(deadline: .now() + displayTime) {
        self.recursiveShowUpEmotion(label: label, index: index + 1)
    }
}

在您的方案中,您延迟了 label.text 赋值,而不是索引赋值。因此,当循环执行时,将立即达到 9。然后在索引 9 处内 10 次。这就是为什么你总是看到.indexDispatchQueueJoyful

评论

1赞 HangarRash 11/17/2023
没有理由成为财产。使其成为此函数的参数。index
0赞 MarkB 12/16/2023 #2

谢谢大家。我无法让提议的递归方法起作用,但这可能就是我应用它的方式。

在 Foti Dim 的大力帮助下,我开发了以下内容:

var displayTime = 5.0
var chosenLabel = 0

func layoutForCharacter() {
    // set up frame and background color
    emotionView = UIView(frame: view.bounds)
    emotionView?.backgroundColor = UIColor.init(hue: 0.563, saturation: 1.0, brightness: 0.93, alpha: 1.0)
    
    let labelLabel = UILabel(frame: CGRect(x: 0, y: 400 , width: view.frame.size.width, height: 20))
    labelLabel.textAlignment = .center
    
    // Display each label for displayTime seconds
    chosenLabel = 0
    
    view?.addSubview(labelLabel)
    
    // Use a timer to display each label
    var chosenLabel = 0
    Timer.scheduledTimer(withTimeInterval: displayTime, repeats: true) { [self] timer in
        // labelLabel.text = String (chosenLabel)
        labelLabel.text = self.labels[chosenLabel]
        
        chosenLabel += 1
        if chosenLabel == self.labels.count {
            timer.invalidate()
            DispatchQueue.main.asyncAfter(deadline: .now() + self.displayTime) {
                self.layoutForConnected()
            }
        }
    }
}

评论

0赞 HangarRash 12/16/2023
与原始代码一样,每次调用 时都会不断添加新标签。layoutForCharacter