Reputation: 123
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)
})
Upvotes: 2
Views: 2187
Reputation: 54591
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:
Upvotes: 1