Dalija Prasnikar Dalija Prasnikar - 1 month ago 11
Swift Question

Handling NSData (Data) range exceptions

Using

NSData
(or
Data
) for reading bytes using
getBytes
(
copyBytes
) can throw NSRangeException. I don't know how to catch them.

I know that for
NS
classes, including
NSData
, I would have to use Objective-C wrapper to catch and handle exception but I am a bit surprised to see that
Data
also throws exception that Swift cannot handle natively.

Am I missing something obvious? Is there a way I can catch those using pure Swift? Or is there any other method that throws Swift handleable errors?

Code example that fails (in reality I am using data created from file)

// Using NSData

let dataBytes:[UInt8] = [0xff, 0x00, 0x11, 0x22]
let data = NSData(bytes: dataBytes, length: dataBytes.count)
let dataRange = NSRange(location: 2, length: 4)

var result = [UInt8](repeating: 0, count: 4)

do
{
try data.getBytes(&result, range: dataRange)
print("OK")
}
catch
{
print("FAIL")
}


// Using Data

let dataBytes:[UInt8] = [0xff, 0x00, 0x11, 0x22]
let data = Data(dataBytes)
let dataRange = Range(2..<6)

var result = [UInt8](repeating: 0, count: 4)

do
{
try data.copyBytes(to: &result, from: dataRange)
print("OK")
}
catch
{
print("FAIL")
}


Note: Code in question also shows two warnings (as expected, because Swift is not capable of handling those) but I added those
try...catch
block just to show what I want to use.


No calls to throwing functions occur within 'try' expression

'catch' block is unreachable because no errors are thrown in 'do' block

Answer

You need to check that the the upper index of the range you're using isn't out of range for your Data:

if dataRange.upperBound <= data.count {
    data.copyBytes(to: &result, from: dataRange)
}

You can think of Data more like an array/collection. copyBytes will fail without a catchable exception for the same reason anArray[1] will fail for a single item array.