4

For example following code:

while let data = Provider.getData() {
    ...
}

With Swift 2 you get two errors:
Initializer for conditional binding must have Optional type, not 'String'
Call can throw, but it is not marked with 'try' and the error is not handled.

What is the best solution to do error handling here…
…if I want to handle the error in this method.
…if I want to throw the error up.

flashspys
  • 844
  • 9
  • 20

3 Answers3

6

Your getData( ) function returns a String value not an optional value. So you should change return type of getData function to optional value type using ? operator

while let always expects an optional value, if your getData function always returns a string value then using while let makes no sense because you are telling the compiler intentionally that getData function will always return a String value and trying to unwrap it, so we shouldn't unwrap a nonoptional value.

Code for error handling ( Written Keeping Swifter in mind ) :

private func nextLine() throws -> String?{
     var returnData : String? = ""

     if arc4random_uniform(7) != 3 {
     returnData = "Genreated Random number other than 3"
     }else{
         throw NSError(domain: "Generated random number 3", code: 111, userInfo: nil)
      }
     return returnData
}

do {
     while let headerLine =  try nextLine() {
     //do something with the header
     print(headerLine)
     }
 }catch{

       //Handle exception
       print(error)
 }

nextLine function returns a string telling "Generated Random number other than 3" if generated number is not equal to 3,or else it will throw an exception which can be handled in the catch block.Here I have potentially made nextLine function to return an optional value.If I remove ? from return type of nextLine function. It will give you an error telling "Initializer for conditional value must have optional type not String", it means compiler is trying to unwrap a non optional value which makes no sense.

Consider :

  var someIntegerValue = 5

  if let x = someIntegerValue
  {
    // it will give an error
  }

Above code will give you an error telling "Intializer for conditional binding must have Optional type,not Int",because even here we are trying to unwrap a non optional value.

 If you replace var some = 5 with var some : Int? = 5 it will be all right.

Error/Exception Handling :

you can make use of try keyword before fetching the value which should be inturn written inside do block ,it will either fetch value or it will fire an exception,exception should be handled inside catch block.

Shailesh Chandavar
  • 1,614
  • 14
  • 20
0

Now that getData() throws we would expect for it to be an explicitly unwrapped String, rather than an optional String, but while let requires an Optional so we can cast to String?

Note, the error-handling is done by wrapping this code in a function that throws. As far as I know, there is no error-handling inside of the while let loop.

override func viewDidLoad() {
    super.viewDidLoad()

    do {
        try loop()
    } catch {
        print("some error")
    }
}

func loop() throws {
    while let data = try getData() as String? {
        print(data)
    }
}

// This is a pseudo function
func getData() throws -> String {
    if arc4random_uniform(10) != 5 {
        return "0"
    } else {
        throw NSError(domain: "d", code: 0, userInfo: nil)
    }
}
Ian
  • 12,538
  • 5
  • 43
  • 62
  • When using this I still got the first error " Initializer for conditional binding must have Optional type, not 'String' ". As workaround I use `while let data try Provider.getData() as String? {…}` is there solution without the unnecessary casting? – flashspys Jun 09 '15 at 22:29
  • Does your getData() function not return NSData? – Ian Jun 09 '15 at 22:30
  • My getData return a 'String' but for any reason I'm not able to reproduce the error in a playground. It's only present in my app (at several locations) – flashspys Jun 09 '15 at 22:37
  • [screenshot](http://puu.sh/iiRsK/51493f8f26.png) this is code from the open source project 'Swifter' I'm trying to convert to Swift 2. [original File](https://github.com/glock45/swifter/blob/master/Common/HttpParser.swift#L73). As you can see the calling method does not return an explicitly unwrapped String. That's the thing I'm wondering about. – flashspys Jun 09 '15 at 22:58
0

while let data = ... means that data is possibly nil. But in your code

Provider.getData()

must be returning a non-nil value. You only use that syntax "while let data = ... " when you're not sure if it will be nil or not.

ShowPony
  • 162
  • 1
  • 4