Convert NSData to Integer in Swift

In Objective-C, the code looked very good and worked flawlessly,

NSInteger random = arc4random_uniform(99) + 1 NSData *data = [NSData dataWithBytes:& random length: sizeof(random)]; int value = *(int*)([data bytes]); 

How can this be done in Swift?

+7
integer swift nsdata
source share
6 answers

Like this:

 var src: NSInteger = 2525 var out: NSInteger = 0 let data = NSData(bytes: &src, length: sizeof(NSInteger)) data.getBytes(&out, length: sizeof(NSInteger)) println(out) // ==> 2525 
+14
source share

For Swift 3, you can do this (small end, but similar for large):

 func getInt(fromData data: Data, start: Int) -> Int32 { let intBits = data.withUnsafeBytes({(bytePointer: UnsafePointer<UInt8>) -> Int32 in bytePointer.advanced(by: start).withMemoryRebound(to: Int32.self, capacity: 4) { pointer in return pointer.pointee } }) return Int32(littleEndian: intBits) } 

You can change this, add generics, etc., to match other primitive types (and vary it depending on the nature of the data bytes).

+6
source share

In Swift 4:

There are a few things to consider when extracting an integer value from a Data stream. Signature and Endianse. So I came up with a function in the extension to Data that tells Signedness from the type of integer you want to extract, and passes Endianess and Index as parameters. The types of integers that can be extracted conform to the FixedWidthInteger protocol.

Reminder: This function does not check if the Index range is inside the boundaries of the Data buffer, so that it may crash depending on the size of the type being retrieved due to the end of the buffer.

 extension Data { enum Endianness { case BigEndian case LittleEndian } func scanValue<T: FixedWidthInteger>(at index: Data.Index, endianess: Endianness) -> T { let number: T = self.subdata(in: index..<index + MemoryLayout<T>.size).withUnsafeBytes({ $0.pointee }) switch endianess { case .BigEndian: return number.bigEndian case .LittleEndian: return number.littleEndian } } } 

Example:

 let data = Data(bytes: [0xFF,0x1F,0x1F,0xFF]) let number1 = data.scanValue(at: 0, endianess: .LittleEndian) as UInt16 let number2 = data.scanValue(at: 0, endianess: .BigEndian) as UInt16 let number3: Int16 = data.scanValue(at: 2, endianess: .LittleEndian) let number4: Int16 = data.scanValue(at: 2, endianess: .BigEndian) 

Results:

number1 is 8191
number2 is 65311
number3 is -225
number4 is 8191

Watch function calls to see how the type to be retrieved is inferred. Of course, Endianess doesn't make sense for Int8 or UInt8 , but the function works as expected.

Values ​​can later be added to Int if necessary.

+6
source share

You may find this method useful if you do this a lot:

 func readInteger<T : IntegerType>(data : NSData, start : Int) -> T { var d : T = 0 data.getBytes(&d, range: NSRange(location: start, length: sizeof(T))) return d } 

The function takes as a parameter the starting position in the data for reading a numeric type and returns a value of type a, which is deduced from what you assign to it.

For example:

 let i : UInt32 = readInteger(data, 10); 

reads an integer of 4 bytes from position 10 in the data.

If you change UInt32 to UInt16 , it will read two bytes.

+5
source share

Data for interger thanks @rghome

 // MARK: - Extensions Data extension Data { /// To interger Data by range /// /// - Parameters: /// - data: Data /// - startRange: StartRange /// - endRange: EndRange /// - Returns: Integer Typed func toInterger<T : Integer>(withData data: NSData, withStartRange startRange: Int, withSizeRange endRange: Int) -> T { var d : T = 0 (self as NSData).getBytes(&d, range: NSRange(location: startRange, length: endRange)) return d } } 101010 let value:Int = Data().toInterger(withStartRange: 0, withEndRange: 2) get 10 get 2 Int 
0
source share

My contribution with quick extension 3.1:

 extension NSData{ var int : Int{ var out: Int = 0 self.getBytes(&out, length: MemoryLayout<Int>.size) return out } } 

Just call. To get your value, for example:

 let value = 50 let data = NSData(bytes: &value, length: 4) print(data.int) 
0
source share

All Articles