Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Save StewartLynch/94f5d2fe8eb19c7c418efc3731b05f72 to your computer and use it in GitHub Desktop.
Save StewartLynch/94f5d2fe8eb19c7c418efc3731b05f72 to your computer and use it in GitHub Desktop.
Is there a better way?
// is there a better way to do this?
// I want to be able to execute something after all of the items have printed
func doIt() {
let numItems = 3
for item in 0...numItems {
DispatchQueue.main.asyncAfter(deadline: .now() + (Double(item) * 1)) {
print(item)
}
}
DispatchQueue.main.asyncAfter(deadline: .now() + Double(numItems + 1)) {
print("Done")
}
}
doIt()
@tunds
Copy link

tunds commented Apr 14, 2022

Hey Stewart try this


//
//  ContentView.swift
//  DummyProject
//
//  Created by Tunde Adegoroye on 14/04/2022.
//

import SwiftUI

struct Box: Identifiable, Equatable {
    let id = UUID()
    let color: Color
    var title: String
}

extension Box {
    static var dummy: [Box] = [
    
        .init(color: .yellow, title: ""),
        .init(color: .pink, title: ""),
        .init(color: .red, title: ""),
        .init(color: .blue, title: ""),
        .init(color: .orange, title: ""),
        .init(color: .pink, title: "")
    ]
}

struct ContentView: View {
    
    @State private var boxes: [Box] = []
    
    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(boxes) { box in
                    ZStack {
                        RoundedRectangle(cornerRadius: 10, style: .continuous)
                            .fill(box.color)
                            .frame(width: 100, height: 100)
                        if !box.title.isEmpty {
                            Text(box.title)
                                .transition(.opacity)
                        }
                    }
                    .transition(.opacity.combined(with: .scale))
                }
            }
            .padding()
            .animation(.easeInOut, value: boxes)
        }
        .task {
            await doIt()
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

private extension ContentView {
    func doIt() async {
        let items = Box.dummy
        for (index, box) in items.enumerated() {
            try? await Task.sleep(seconds: (Double(index) * 0.25))
            self.boxes.append(box)
        }
        
        try? await Task.sleep(seconds: (Double(items.count + 1)))

        await updateTitles()
    }
    
    func updateTitles() async {
        for (index, _) in boxes.enumerated() {
            self.boxes[index].title = "Item# \(index)"
        }
    }
}

// https://www.hackingwithswift.com/quick-start/concurrency/how-to-make-a-task-sleep
extension Task where Success == Never, Failure == Never {
    static func sleep(seconds: Double) async throws {
        let duration = UInt64(seconds * 1_000_000_000)
        try await Task.sleep(nanoseconds: duration)
    }
}

//func doIt() async {
//    let numItems = 3
//    for item in 0...numItems {
//        DispatchQueue.main.asyncAfter(deadline: .now() + (Double(item) * 1)) {
//            print(item)
//        }
//    }
//    DispatchQueue.main.asyncAfter(deadline: .now() + Double(numItems + 1)) {
//        print("Done")
//    }
//}


@StewartLynch
Copy link
Author

StewartLynch commented Apr 14, 2022

Thanks. This was above and beyond and more than I actually needed. The solution for my example is just

func doIt() async {
let numItems = 3
for item in 0...numItems {
try? await Task.sleep(seconds: 1)
print(item)
}

try? await Task.sleep(seconds: 1 )
await completion()
}

func completion() async {
print("Done")
}

Task {
await doIt()
}

extension Task where Success == Never, Failure == Never {
static func sleep(seconds: Double) async throws {
let duration = UInt64(seconds * 1_000_000_000)
try await Task.sleep(nanoseconds: duration)
}
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment