'Unexpected non-void return value in void function' in swiftui

Maanas

Basically, I'm having trouble returning a url in the form of a string in my API call.

I'm trying to implement abstraction by having one big function that takes a 'breed' parameter to call into its endpoint. That way I avoid writing the same exact function multiple times. The functions getMamalute(), getGolden(), etc. all pass in this parameter to get a URL so that I can display it in my View as an Image -- as you can probably tell. But I'm getting the following error 'Unexpected non-void return value in void function' at the return line in the 'getFavoriteDoggo' function. Do I need to use a completion handler? If so, how will that look like?

    @Published var mamaluteImg = ""
    @Published var goldenImg = ""
    @Published var samoyedImg = ""
    @Published var chowImg = ""
    @Published var huskyImg = ""

    func getMamalute() -> String{
        return getFavoriteDoggo(breed: "malamute")
    }
    
    func getChowChow() -> String{
        return getFavoriteDoggo(breed: "chow")
    }
    
    func getHusky() -> String{
        return getFavoriteDoggo(breed: "husky")
    }
    
    func getSamoyed() -> String{
        return getFavoriteDoggo(breed: "samoyed")
    }
    
    func getGoldenRetriever() -> String{
        return getFavoriteDoggo(breed: "retriever/golden")
    }

func getFavoriteDoggo(breed: String) -> String{
        
        guard let url = URL(string: "https://dog.ceo/api/breed/\(breed)/images/random") else {
            print("Trouble parsing url")
            return ""
        }
        
        let request = URLRequest(url: url)
        
        URLSession.shared.dataTask(with: request){ data, response, error in
            if error != nil {
                print((error?.localizedDescription)!)
                return
            }
            
            if let data = data {
                let response = try! JSON(data: data)
//                let randoIndex = Int.random(in: 0...(response.count - 1))
                let img = response["message"]
                
//                print(img)
                
//                DispatchQueue.main.async {
//                    self.mamaluteImg = img.string!
//                }
                return img.string
            }
        }.resume()
    }

Hopefully I explained my problem clearly, if not my apologies my brain is running really low on battery juice, so I'd be more than happy to help clarify down below:)

Thanks once again!

Adrien

You are using an asynchronous method (dataTask). You don't know when it will be finished running (network request). It therefore cannot have a return value. When it finishes it executes the closure (URLSession.shared.dataTask (with: request) {// this block}).

You would certainly like to do it this way:

class DogManager {
    var imageInfos: String?
    
    func getFavoriteDoggo(breed: String) {
        guard let url = URL(string: "https://dog.ceo/api/breed/\(breed)/images/random") else {
            print("Trouble parsing url")
            return
        }

        URLSession.shared.dataTask(with: url) { data, response, error in
            guard error == nil, (response as? HTTPURLResponse)?.statusCode == 200 else {
                return
            }
            if let data = data {
                self.imageInfos = String(data: data, encoding: .utf8)
                print(self.imageInfos ?? "no infos")
            }
        }.resume()
    }
}

let manager = DogManager()
manager.getFavoriteDoggo(breed: "retriever/golden")

You can test in a Playground.

Now if you want to use SwiftUI and your View is redrawn when imageInfos changes you have to change your class to ObservableObject:

class DogManager: ObservableObject {
    @Published var imageInfos: String?
    //....//
}

And use it like this:

struct MainView: View {
    @StateObject private var dm = DogManager()

    var body: some View {
        Text(dm.imageInfos ?? "nothing")
            .onAppear {
                dm.getFavoriteDoggo(breed: "retriever/golden")
            }
    }
}

iOS15 :

Note that with the introduction of async / await (iOS15) you can write asynchronous methods that have return values ​​(like you did) :

    @available(iOS 15.0, *)
    func getFavoriteDoggo(breed: String) async -> String? {
        guard let url = URL(string: "https://dog.ceo/api/breed/\(breed)/images/random"),
              let (data, response) = try? await URLSession.shared.data(from: url),
              (response as? HTTPURLResponse)?.statusCode == 200 else { return nil }
        return String(data: data, encoding: .utf8)
    }

You can use it with the new .task modifier :

struct MainView: View {
    var dm = DogManager()
    @State private var imageInfos: String?
    var body: some View {
        Text(imageInfos ?? "nothing")
            .task {
                await imageInfos = dm.getFavoriteDoggo(breed: "retriever/golden")
            }
    }
}

EDIT :

"Hey thank you for helping me out, but this would only work for only 1 dog breed."

First, let's create a new Dog structure. A Dog has a breed and the information on its image, which initially does not exist (nil).

struct Dog: Identifiable {
    let id = UUID()
    let breed: String
    var imageInfos: String?

    init(_ breed: String) {
        self.breed = breed
    }
}

Our view will show an array of dogs:

@State private var dogs: [Dog] = ["malamute", "chow", "husky", "samoyed"].map(Dog.init)

Now we change our function that fetches the image of a dog: it takes a Dog as a parameter, and returns (when it has finished) a Dog (with imageInfos filled) :

func updateImageOf(dog: Dog) async -> Dog {
        var newDog = dog
        guard let url = URL(string: "https://dog.ceo/api/breed/\(dog.breed)/images/random"),
              let (data, response) = try? await URLSession.shared.data(from: url),
              (response as? HTTPURLResponse)?.statusCode == 200 else { return dog }
        newDog.imageInfos = String(data: data, encoding: .utf8)
        return newDog
    }

We create a second function that does the same for several dogs.

func updateImagesOf(favoriteDogs: [Dog]) async -> [Dog] {
        var results: [Dog] = []
        await withTaskGroup(of: Dog.self) { group in
            for dog in favoriteDogs {
                group.async {
                    await self.updateImageOf(dog: dog)
                }
            }
            for await result in group {
                results.append(result)
            }
        }
        return results
    }

We use this function in our View:

struct MainView: View {
    var dm = DogManager()

    @State private var dogs: [Dog] = ["malamute", "chow", "husky", "samoyed"].map(Dog.init)

    var body: some View {
        List(dogs) { dog in
            HStack {
                Text(dog.breed)
                    .padding(.trailing, 40)
                Text(dog.imageInfos ?? "rien")
            }
        }
        .task {
            await dogs = dm.updateImagesOf(favoriteDogs: dogs)
        }
    }
}

It works (Simulator, Xcode 13 beta2)

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

unexpected non void return value in void function

Unexpected non-void return value in void function

Unexpected Non-Void Return Value In Void Function (Swift 2.0)

Unexpected non-void return value in void function (Swift 3)

Swift NumberOfRowsInSection Unexpected non-void return value in void function

why in this code would I be getting "Unexpected non-void return value in void function"

Retrieve product localised price - Unexpected non-void return value in void function

unexpected non-void return value in void function in new Swift class

Unexpected non-void return value in void function - Swift 4 (Firebase, Firestore)

Unexpected non-void return value in void function swift 4 using json serialisation

Unexpected non-void return value in void function Swift3

Why does Unexpected non-void return value in void function happen?

Unexpected non-void return value in void function(swift3)

Class understanding: Unexpected non-void return value in void function (swift 3)

Return value void * in a function

swift Non-void function should return a value in a guard let

Restrict function return value to void

Is the return command in a non-void function necessary?

Type No return, in function returning non-void

Non-void function potential lack of return

What is the return value if we dont return anything from a non void return typed function in c++?[Experimental]

What's the return value of a non-void function missing return statement?

Warning 'return' with no value, in function returning non-void - What should it return?

void function pointer return value in C

Unclear about return value of a void function in C

Should i return a value for a Future<void> Function?

Why does a void function return a value?

How to return a value from Void Function?

Calling a non-void function without using its return value. What actually happens?

TOP Ranking

  1. 1

    Failed to listen on localhost:8000 (reason: Cannot assign requested address)

  2. 2

    pump.io port in URL

  3. 3

    How to import an asset in swift using Bundle.main.path() in a react-native native module

  4. 4

    Loopback Error: connect ECONNREFUSED 127.0.0.1:3306 (MAMP)

  5. 5

    Compiler error CS0246 (type or namespace not found) on using Ninject in ASP.NET vNext

  6. 6

    BigQuery - concatenate ignoring NULL

  7. 7

    Spring Boot JPA PostgreSQL Web App - Internal Authentication Error

  8. 8

    ggplotly no applicable method for 'plotly_build' applied to an object of class "NULL" if statements

  9. 9

    ngClass error (Can't bind ngClass since it isn't a known property of div) in Angular 11.0.3

  10. 10

    How to remove the extra space from right in a webview?

  11. 11

    Change dd-mm-yyyy date format of dataframe date column to yyyy-mm-dd

  12. 12

    Jquery different data trapped from direct mousedown event and simulation via $(this).trigger('mousedown');

  13. 13

    maven-jaxb2-plugin cannot generate classes due to two declarations cause a collision in ObjectFactory class

  14. 14

    java.lang.NullPointerException: Cannot read the array length because "<local3>" is null

  15. 15

    How to use merge windows unallocated space into Ubuntu using GParted?

  16. 16

    flutter: dropdown item programmatically unselect problem

  17. 17

    Pandas - check if dataframe has negative value in any column

  18. 18

    Nuget add packages gives access denied errors

  19. 19

    Can't pre-populate phone number and message body in SMS link on iPhones when SMS app is not running in the background

  20. 20

    Generate random UUIDv4 with Elm

  21. 21

    Client secret not provided in request error with Keycloak

HotTag

Archive