UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Day 8 Throwing Functions, Generalizing the function

Forums > 100 Days of SwiftUI

I have a question regarding gereralizing throwing functions, specifically with regard to addind the do/catch to it's own function. The examples in 100 Days of SwiftUI as well as other documentation I found online shows that to use throwing functions, we should create an enum, a function, and then use do/catch to try the code. My question is where should the do catch go? What is the best way to generalize it? In the Day 8 example that I used to guide my code for Checkpoint 4 - Integer square, it seems that I should hardcode the square.

See the example in the the section labeled "START ORIGINAL EXAMPLE" where I created a function, "integerSquare"

I then decided to to rename "integerSquare" to integerSquareRunner, that gets called by "integerSquare." That way, "integerSquare" could be called with different inputs, such as: integerSquare(of: 15) That code can be found in the section labeled "START UPDATED EXAMPLE"

It works as I intended, but is this good practice? Is there another way that this same functionality can be accomplished?

Thank you in advance...

import UIKit

enum SquareRootError: Error {
    case outOfBounds, noRoot
}

// **** START ORIGINAL EXAMPLE /*

func integerSquare(of num: Int) throws -> Int {
     if num < 1 || num > 10000 { throw SquareRootError.outOfBounds}
     for i in 1...10000 {
         if i * i == num {
             return i
         }
     }

     throw SquareRootError.noRoot
 }

 do {
     var square = try integerSquare(of: 10000)
     print(square)
 }
 catch SquareRootError.outOfBounds {
     print("The number that you entered is out of bounds.")
 }
 catch SquareRootError.noRoot {
     print("There is no perfect root for number that you entered.")
 }

*/
//**** END ORIGINAL EXAMPLE

// **** START UPDATED EXAMPLE

func integerSquareRunner(of num: Int) throws -> Int {
    if num < 1 || num > 10000 { throw SquareRootError.outOfBounds}
    for i in 1...10000 {
        if i * i == num {
            return i
        }
    }

    throw SquareRootError.noRoot
}

func integerSquare(of num: Int){
    do {
        var square = try integerSquareRunner(of: num)
        print(square)
    }
    catch SquareRootError.outOfBounds {
        print("The number that you entered is out of bounds.")
    }
    catch SquareRootError.noRoot {
        print("There is no perfect root for number that you entered.")
    }
    catch {
        print("There was an error: \(error.localizedDescription)")
    }
}

integerSquare(of: 15)

//**** END UPDATED EXAMPLE

   

Please edit your post and put ALL YOUR CODE inside the code markup tags. Thanks.

   

You should put the do ... catch wherever you plan to handle the error.

Creating a whole new function just to have somewhere to catch errors is overcomplicating things. Your first example is the way to go.

1      

You can reduce the amount of zeros here to 100.....

for i in 1...10000 {

You are returning i x i from range 1 to 10000. 100 x 100 is 10000. 100 x 101 is higher than 10000, so there's not much point in that.

As far as do and catch goes try not to write code that will crash :)!

   

I would change a few thing (not sure that you have covered this in the 100Days) but use a guard instead of if in the method. At the moment you are learning about them and can not see how they would work so did this as an example. You have a model class that you would put the throwing method in

@Observable
class SomeModel {
    var inputNumber = 0

    func squareRoot(of num: Int) throws -> Int {
         guard num > 1 && num < 10000 else { throw SquareRootError.outOfBounds }

         for i in 1...100 {
             if i * i == num {
                 return i
             }
         }

         throw SquareRootError.noRoot
     }
}

Then in the View it can be used

struct ContentView: View {
    @State private var model = SomeModel()

    var displaySquareRoot: String {
        do {
            let root = try model.squareRoot(of: model.inputNumber)
            return "Answer: \(root)"
        } catch SquareRootError.outOfBounds {
            return "The number that you entered is out of bounds."
        } catch SquareRootError.noRoot {
            return "There is no perfect root for number that you entered."
        } catch {
            return "There was an error: \(error.localizedDescription)"
        }
    }

    var body: some View {
        VStack {
            LabeledContent("Enter Number: ") {
                TextField("Enter Number", value: $model.inputNumber, format: .number)
                    .textFieldStyle(.roundedBorder)
                    .multilineTextAlignment(.center)
            }

            Text(displaySquareRoot)
                .padding()

        }
        .padding()
    }
}

As you can see that handling errors at the call site to display to user.

   

Hacking with Swift is sponsored by RevenueCat.

SPONSORED Take the pain out of configuring and testing your paywalls. RevenueCat's Paywalls allow you to remotely configure your entire paywall view without any code changes or app updates.

Learn more here

Sponsor Hacking with Swift and reach the world's largest Swift community!

Reply to this topic…

You need to create an account or log in to reply.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.