swiftswiftuiswift-concurrency

Task error: Type of expression is ambiguous without a type annotation


PhotosPicker(selection: $selectedItem, matching: .videos){
    Image(systemName: "camera.fill")
        .resizable()
        .aspectRatio(contentMode: .fit)
        .frame(height: 20)
        .padding(2)

}
.onChange(of: selectedItem) { newItem in
    
    videoURL = nil
    
    Task {

        if let data = try? await newItem?.loadTransferable(type: Data.self) {
            
            let bytes = Double(data.count)
            let megabytes = bytes / (8 * 1024 * 1024)
            
            print("size:")
            print(megabytes)

            
            if(megabytes > 32){
                print("too big")
            }else{

                let tempFile = TemporaryMediaFile(withData: data)
                
                let asset = tempFile.avAsset
                
                let vidWidth = await asset?.naturalSize()?.width
                let vidHeight = await asset?.naturalSize()?.height
                
                videoHeight = 160 * (vidHeight! / vidWidth!)
                videoURL = tempFile.url

            }
 
        }else{
            print("picking failed")
        }
    }
}

I get

Type of expression is ambiguous without a type annotation on 'Task'

How to fix it?


Solution

  • Use the task(id:priority:_:) modifier instead of a detached Task.

    Change your code to this:

    PhotosPicker(selection: $selectedItem, matching: .videos) {
        Image(systemName: "camera.fill")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(height: 20)
            .padding(2)
    }
    .task(id: selectedItem) {
    
         videoURL = nil
    
         do {
        
            if let data = try await selectedItem?.loadTransferable(type: Data.self) {
                
                let bytes = Double(data.count)
                let megabytes = bytes / (8 * 1024 * 1024)
                
                print("size:")
                print(megabytes)
                
                if (megabytes > 32) {
                    print("too big")
                } else {
    
                    let tempFile = TemporaryMediaFile(withData: data)
                    
                    let asset = tempFile.avAsset
                    
                    let vidWidth = await asset?.naturalSize()?.width
                    let vidHeight = await asset?.naturalSize()?.height
                    
                    videoHeight = 160 * (vidHeight! / vidWidth!)
                    videoURL = tempFile.url
                }
            } else {
                print("picking failed")
            }
        
        } catch {
            print(error)
        }
    }
    

    Also note that that I changed the optional call try? to a regular throwing try and catch the error.