struct FunctionTypes {
var syncNonThrowing: () -> Void
var syncThrowing: () throws -> Void
var asyncNonThrowing: () async -> Void
var asyncThrowing: () async throws -> Void
mutating func demonstrateConversions() {
// Okay to add 'async' and/or 'throws'
asyncNonThrowing = syncNonThrowing
asyncThrowing = syncThrowing
syncThrowing = syncNonThrowing
asyncThrowing = asyncNonThrowing
// Error to remove 'async' or 'throws'
syncNonThrowing = asyncNonThrowing // error
syncThrowing = asyncThrowing // error
syncNonThrowing = syncThrowing // error
asyncNonThrowing = syncThrowing // error
}
}
// func redirectURL(for url: URL) async -> URL { ... }
// func dataTask(with: URL) async throws -> (Data, URLResponse) { ... }
let newURL = await server.redirectURL(for: url)
let (data, response) = try await session.dataTask(with: newURL)
https://green1229.tistory.com/340
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
// MARK: METHOD 1 - Using Async/Await
Task {
if let imageDetail = try? await downloadImageAndMetadata(imageNumber: 1) {
self.imageView.image = imageDetail.image
self.metadata.text = "\(imageDetail.metadata.name) (\(imageDetail.metadata.firstAppearance) - \(imageDetail.metadata.year))"
}
}
// MARK: METHOD 2 - Using async properties
// Task {
// let character = Character(id: 1)
// if
// let metadata = try? await character.metadata,
// let image = try? await character.image{
// imageView.image = image
// self.metadata.text = "\(metadata.name) (\(metadata.firstAppearance) - \(metadata.year))"
// }
// }
// MARK: Method 3 - Using Callbacks
// downloadImageAndMetadata(imageNumber: 1) { imageDetail, error in
// DispatchQueue.main.async {
// if let imageDetail = imageDetail {
// self.imageView.image = imageDetail.image
// self.metadata.text = "\(imageDetail.metadata.name) (\(imageDetail.metadata.firstAppearance) - \(imageDetail.metadata.year))"
// }
// }
// } 예제 앱!!!!!!!!!!!!!!!!!
}
task의 용도는 펑션을 만들때 꼭 앞에 async를 붙여주어야한다 하지만 이미 apple에서 만들어져있는 method를 쓸때는 async를 써줄수가 없으므로 그럴경우네느 Task {}안에 넣어서 쓰면 된다 Task안에는 async나 sync 둘다 사용할수 있다
이거 좀 중요함
두개의 async await가 있고 두개가 서로 의존하지 않는다면 두개를 동시에 진행해도 상관이 없다
한개가 끝나고 그다음것을 진행하는것보다 더 효율적인 방법이다 그런데 어떻게 할까?
ㅇㅇ 이렇게 하면됨
func downloadImage(imageNumber: Int) async throws -> UIImage {
try Task.checkCancellation()
let imageUrl = URL(string: "https://www.andyibanez.com/fairesepages.github.io/tutorials/async-await/part3/\(imageNumber).png")!
let imageRequest = URLRequest(url: imageUrl)
let (data, imageResponse) = try await URLSession.shared.data(for: imageRequest)
guard let image = UIImage(data: data), (imageResponse as? HTTPURLResponse)?.statusCode == 200 else {
throw ImageDownloadError.badImage
}
return image
}
func downloadMetadata(for id: Int) async throws -> ImageMetadata {
try Task.checkCancellation()
let metadataUrl = URL(string: "https://www.andyibanez.com/fairesepages.github.io/tutorials/async-await/part3/\(id).json")!
let metadataRequest = URLRequest(url: metadataUrl)
let (data, metadataResponse) = try await URLSession.shared.data(for: metadataRequest)
guard (metadataResponse as? HTTPURLResponse)?.statusCode == 200 else {
throw ImageDownloadError.invalidMetadata
}
return try JSONDecoder().decode(ImageMetadata.self, from: data)
}
func downloadImageAndMetadata(imageNumber: Int) async throws -> DetailedImage {
async let image = downloadImage(imageNumber: imageNumber)
async let metadata = downloadMetadata(for: imageNumber)
return try DetailedImage(image: await image, metadata: await metadata)
}
// NEW FUNCTION
func downloadMultipleImagesWithMetadata(images: Int...) async throws -> [DetailedImage]{
var imagesMetadata: [DetailedImage] = []
for image in images {
print(image)
async let image = downloadImageAndMetadata(imageNumber: image)
imagesMetadata += [try await image]
}
return imagesMetadata
} Task Tree Sample
of 있는곳에 for loop을 돌려서 나오는 타입을 적어줌
이 경우에는 uiimage
여기서 주의할점은 image가 순서대로 나오지 않으므로 딕셔너리를 이용해서 순서를 쫓아가는등 하는 방법이 있어야함