Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.6k views
in Technique[技术] by (71.8m points)

swiftui - Swift: return value every x seconds

I'm trying to generate random string every 10 seconds. I put this function in a class in another file and will call the function in another view controller. But now I'm not getting any output when I call it. How to can I fix this code

 class Data{

    static let instance = Data()

    func randomString(of length: Int){
       let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
       var s = ""
       for _ in 0 ..< length {
           s.append(letters.randomElement()!)
        
           print("(s) = I'm in randomString Func")
       }
       DispatchQueue.main.asyncAfter(deadline: .now() + 10.0) { [weak self] in
           self?.randomString(of: 5)
           }
   }


 }

in a view controller I put it under a button action and call it with this code

 Button(action: {
                info = Data.instance.randomString(of:5)
                print(info)

            }, label: {
                Text ("PRINT")
                    .font(.callout)
                    .foregroundColor(Color.primary)
            })
question from:https://stackoverflow.com/questions/65903738/swift-return-value-every-x-seconds

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

A possible solution is to use the Timer from the Combine framework:

struct ContentView: View {
    @State private var text = "initial text"
    @State private var timer: AnyCancellable?

    var body: some View {
        Text(text)
        Button(action: startTimer) { // start timer on button tap, alternatively put it in `onAppear`
            Text("Start timer")
        }
    }

    func startTimer() {
        // start timer (tick every 10 seconds)
        timer = Timer.publish(every: 10, on: .main, in: .common)
            .autoconnect()
            .sink { _ in
                text = DataGenerator.instance.randomString(of: 5)
            }
    }
}

You also need to return the String from the randomString function. A good thing would also be to rename Data to avoid collisions:

class DataGenerator { // rename the class
    static let instance = DataGenerator()

    func randomString(of length: Int) -> String { // return `String`
        let letters = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"
        var s = ""
        for _ in 0 ..< length {
            s.append(letters.randomElement()!)

            print("(s) = I'm in randomString Func")
        }
        return s // return String, don't call `DispatchQueue.main.async` here
    }
}

You may also consider moving the timer logic out of the view like in:


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...