Catch Any Error, Specially Unexpectedly Found Nil in Swift

Catch any error, specially unexpectedly found nil in swift

You use a do-catch statement to handle errors by running a block of code. If an error is thrown by the code in the do clause, it is matched against the catch clauses to determine which one of them can handle the error.

You use try? to handle an error by converting it to an optional value. If an error is thrown while evaluating the try? expression, the value of the expression is nil. For example, in the following code x and y have the same value and behavior:

func someThrowingFunction() throws -> Int {
// ...
}

let myValue1 = try? someThrowingFunction()

let myValue2: Int?
do {
myValue2 = try someThrowingFunction()
} catch {
myValue2 = nil
}

If someThrowingFunction() throws an error, the value of myValue1 and myValue2 is nil. Otherwise, the value of myValue1 and myValue2 is the value that the function returned. Note that myValue1 and myValue2 are an optional of whatever type someThrowingFunction() returns. Here the function returns an integer, so myValue1 and myValue2 are optional integers.

Using try? lets you write concise error handling code when you want to handle all errors in the same way. For example, the following code uses several approaches to fetch data, or returns nil if all of the approaches fail

func fetchData() -> Data? {
if let data = try? fetchDataFromDisk() { return data }
if let data = try? fetchDataFromServer() { return data }
return nil
}

if you want to check nil value , you can also use like this :-

var myValue: Int?

if let checkValue:Int = myValue {
// run this when checkValue has a value which is not ni
}

How do I catch Index out of range in Swift?

As suggested in comments and other answers it is better to avoid this kind of situations. However, in some cases you might want to check if an item exists in an array and if it does safely return it. For this you can use the below Array extension for safely returning an array item.

Swift 5

extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}

Swift 4

extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}

Swift 3

extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Generator.Element? {
return indices.contains(index) ? self[index] : nil
}
}

Swift 2

extension Array {
subscript (safe index: Int) -> Element? {
return indices ~= index ? self[index] : nil
}
}
  • This way you'll never hit Index out of range
  • You'll have to check if the item is nil

refer this question for more



Trying the Swift3 code in a Playground in Xcode 8.3.2 still leads to a
"crash" when I do let ar = [1,3,4], then let v = ar[5]. Why? – Thomas
Tempelmann May 17 at 17:40

You have to use our customized subscript so instead of let v = ar[5], it wll be let v = ar[safe: 5].

Default getting value from array.

let boo = foo[index]

Add use the customized subscript.

let boo = fee[safe: index]

// And we can warp the result using guard to keep the code going without throwing the exception.
guard let boo = foo[safe: index] else {
return
}

AVCaptureSession Runtime crash. fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)

Looking at your code, you should really try to get out of the habit of force-unwrapping optionals using ! at any opportunity, especially just to “make it compile". Generally speaking, if you ever find yourself writing if something != nil, there’s probably a better way to write what you want. Try looking at the examples in this answer for some idioms to copy. You might also find this answer useful for a high-level explanation of why optionals are useful.

AVCaptureDeviceInput.deviceInputWithDevice returns an AnyObject, and you are force-casting it to a AVCaptureInput with this line:

var deviceInput = AVCaptureDeviceInput.deviceInputWithDevice(captureDevice, error: &err) as! AVCaptureInput

(you don’t need to state the type of deviceInput by the way, Swift can deduce it from the value on the right-hand side)

When you write as!, you are telling the compiler “don’t argue with me, force the result to be of type AVCaptureInput, no questions asked”. If it turns out what is returned is something of a different type, your app will crash with an error.

But then on the next line, you write:

if deviceInput == nil! {

I’m actually quite astonished this compiles at all! But it turns out it does, and it’s not surprising it crashes. Force-unwrapping a value that is nil will crash, and you are doing this in it’s purest form, force-unwrapping a nil literal :)

The problem is, you’ve already stated that deviceInput is a non-optional type AVCaptureInput. Force-casting the result is probably not the right thing to do. As the docs for state,

If the device cannot be opened because it is no longer available or because it is in use, for example, this method returns nil, and the optional outError parameter points to an NSError describing the problem.

The right way to handle this is to check is the result is nil, and act appropriately. So you want to do something like:

if let deviceInput = AVCaptureDeviceInput.deviceInputWithDevice(captureDevice, error: &err) as? AVCaptureInput
// use deviceInput
}
else {
println("error: \(err?.localizedDescription)")
}

Why try/catch block doesn't cover all the runtime exceptions?

try this

..
if let path = URL(string: "someStringForUrl") {

do {
let data = try Data(contentsOf: path)
}
catch {
print("ERROR: \(error)")
}
}
...

AVAudioRecorder - found nil when unwrapping optional

For anyone else looking at this, it then turns out I was using KAudioFile... instead of kAudioFormat in the settings for my recorder

Attempting to start HKLiveWorkout keep getting unexpectedly found nil on session

You shouldn't mask the error into an Optional by using try? thrown by HKWorkoutSession(healthStore: healthStore, configuration: configuration), especially if you already put the statement in a do-catch block. You get a crash, because session is defined as an implicitly unwrapped optional (! mark after the type), which it shouldn't be.

You should define session as a normal optional if it might have a nil value and safely unwrap/optional chain it every time you access it.

class InterfaceController: WKInterfaceController, HKWorkoutSessionDelegate, HKLiveWorkoutBuilderDelegate {

let healthStore = HKHealthStore()
let configuration = HKWorkoutConfiguration()

var session: HKWorkoutSession? = nil
var builder: HKLiveWorkoutBuilder? = nil

func startWorkoutWithHealthStore(){
configuration.activityType = .crossTraining
configuration.locationType = .indoor

do {
session = try HKWorkoutSession(healthStore: healthStore, configuration: configuration)
} catch {
print(error)
session = nil
return
}

builder = session?.associatedWorkoutBuilder()

//Setup session and builder

session?.delegate = self
builder?.delegate = self

builder?.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: configuration)

//Start Session & Builder
session?.startActivity(with: Date())

builder?.beginCollection(withStart: Date()) { (success, error) in
self.setDurationTimerDate() //Start the elapsed time timer
}

}
...
}

API Fetch returns nil

I have never used alamofire directly to make a network request, but seems the error is on how you decode the response, assuming undecodedData is already containing the data you want, your current response model does not decode the "bitcoin" key, hence the struct is nil, you can change your struct to something like

struct BitcoinStats: Codable, Hashable {
let bitcoin: TokenSimplePriceCoingeckoUsdModel
}

struct TokenSimplePriceCoingeckoUsdModel: Codable, Hashable {
let usd, usd_market_cap, usd_24h_vol, usd_24h_change: Double?
let last_updated_at: Int?
}

or you might want to try to decode the value of the "bitcoin" key directly, so you can keep your current struct as is

UPDATE :
Because the JSON has other keys than "bitcoin", this is my proposed solution for decoding the data dynamically without the needs to hardcode the keys:
pastecode.io/s/tkim2jf0

Firebase Remote Config Unexpectedly Found Nil while unwrapping error configValue(forKey:)

You are force unwrapping a string and than an image. Are you sure remote config is nil? It says "file" in your pasted error message.

  • First make sure that the file exists in your asset catalog with the name you require.
  • Second, check the value in Firebase console, and make sure it does not have any unexpected characters.

If you copy pasted the value, probably there is a tab, space or another invisible character left behind.

EDIT: You can try something like this for the first image where you are getting the error:

guard let name = rc.configValue(forKey: "mp1Img1").stringValue else {
print("Remote config is nil for mp1Img1")
return
}

guard let image = UIImage(named: name) else {
print("Image named \(name) does not exist in asset catalog.")
return
}

First guard will be a control for nil remote config value.
Second for a possible missing image. You can always add a breakpoint to see what the values are.



Related Topics



Leave a reply



Submit