Ios 为什么应用程序在NSData getBytes上崩溃?

Ios 为什么应用程序在NSData getBytes上崩溃?,ios,swift,memory-management,nsdata,Ios,Swift,Memory Management,Nsdata,NSData被扩展以确定文件类型: extension NSData { var dataType: String? { // Ensure data length is at least 1 byte guard self.length > 0 else { return nil } // Get first byte var c = [UInt8](count: 1, repeatedValue: 0)

NSData被扩展以确定文件类型:

extension NSData {
    var dataType: String? {

        // Ensure data length is at least 1 byte
        guard self.length > 0 else { return nil }

        // Get first byte
        var c = [UInt8](count: 1, repeatedValue: 0)
        self.getBytes(&c, length: 1)

        // Identify data type
        switch (c[0]) {
        case 0xFF:
            return "jpg"
        case 0x89:
            return "png"
        case 0x47:
            return "gif"
        case 0x49, 0x4D:
            return "tiff"
        default:
            return nil //unknown
        }
    }
}
在从服务器获取的图像数据的
NSData
对象上调用上述方法

dispatch_async(dispatch_get_global_queue(QOS_CLASS_BACKGROUND, 0)) {

    do {
        // Fetch image synchronously from server
        let query = PFQuery(className: <...>)
        let result = try query.getFirstObject()

        guard
            let imageObject = result.objectForKey(<...>) as? PFFile,
            let imageData = try? imageObject.getData(),
            let image = imageData.dataType == "gif" ? UIImage.animatedImageWithAnimatedGIFData(imageData) : UIImage(data: imageData)
        else {
            return
        }

        <...>

    } catch (let error as NSError) {
        <...>
    }
}
使现代化 在代码发生以下变化的情况下,仍然会发生崩溃:

// Get first byte
var c: UInt8 = 0;
self.getBytes(&c, length: 1)
// Get first byte
var c = [UInt8](count: 1, repeatedValue: 0)
c.withUnsafeMutableBufferPointer {
    buffer in
    getBytes(buffer.baseAddress, length: 1)
}

guard c.indices.contains(0) else { return nil }
// Get first byte
var c = UnsafeMutablePointer<UInt8>.alloc(1)
defer { c.dealloc(1) }
self.getBytes(c, length: 1)    

switch (c[0]) { ...
我得到了以下崩溃,包括整个线程,也许有人可以发现一个提示:

Thread 18 Crashed:
0   libsystem_platform.dylib             0x21a8e198 _platform_memmove$VARIANT$CortexA9 + 92
1   Foundation                           0x22512923 __34-[_NSDispatchData getBytes:range:]_block_invoke + 176
2   libdispatch.dylib                    0x218d238d _dispatch_data_apply + 82
3   libdispatch.dylib                    0x218d4a51 dispatch_data_apply + 26
4   Foundation                           0x22512865 -[_NSDispatchData getBytes:range:] + 86
5   Foundation                           0x2267730b -[_NSDispatchData getBytes:length:] + 24
6   MyAppName                               0x00079ba0 partial apply forwarder for (extension in MyAppName):__ObjC.NSData.(dataType.getter : Swift.String?).(closure #1) (NSData+Extension.swift:54)
7   MyAppName                               0x00079c14 partial apply forwarder for reabstraction thunk helper from @callee_owned (@inout Swift.UnsafeMutableBufferPointer<Swift.UInt8>) -> (@unowned (), @error @owned Swift.ErrorType) to @callee_owned (@inout Swift.UnsafeMutableBufferPointer<Swift.UInt8>) -> (@out (), @error @owned Swift.ErrorType) (NSData+Extension.swift:0)
8   MyAppName                               0x00079cb8 generic specialization <Swift.UInt8, ()> of Swift.Array.withUnsafeMutableBufferPointer <A> ((inout Swift.UnsafeMutableBufferPointer<A>) throws -> A1) throws -> A1 (NSData+Extension.swift:0)
9   MyAppName                               0x00079a70 (extension in MyAppName):__ObjC.NSData.dataType.getter : Swift.String? (NSData+Extension.swift:55)
10  MyAppName                               0x00079948 @objc (extension in MyAppName):__ObjC.NSData.dataType.getter : Swift.String? (NSData+Extension.swift:0)
11  MyAppName                               0x000d2264 MyAppName.DataManager.(fetchImagesFromServer (MyAppName.ImageSet) -> ()).(closure #1) (DataManager.swift:1214)
12  libdispatch.dylib                    0x218cd823 _dispatch_call_block_and_release + 8
13  libdispatch.dylib                    0x218dc5e9 _dispatch_root_queue_drain + 1558
14  libdispatch.dylib                    0x218dbfcd _dispatch_worker_thread3 + 94
15  libsystem_pthread.dylib              0x21a91b29 _pthread_wqthread + 1022
16  libsystem_pthread.dylib              0x21a91718 start_wqthread + 6
线程18崩溃:
0 libsystem_platform.dylib 0x21a8e198_platform_memmove$VARIANT$CortexA9+92
1基金会0x22512923α34 - [[NStpReDebug GETByel:Leave::] BythyPosik+ 176
2 libdispatch.dylib 0x218d238d_dispatch_data_apply+82
3 libdispatch.dylib 0x218d4a51调度数据应用+26
4基金会0x22512865 - [γNDSPACCHATDATIONGETBYS:范围:] + 86
5基金会0x226730B-[ [AN NoStReDATA GETByth:Lime::] + 24
6 MyAppName 0x00079ba0部分应用转发器(MyAppName中的扩展名):\uu ObjC.NSData.(dataType.getter:Swift.String?)(闭包#1)(NSData+扩展名.Swift:54)
7 MyAppName 0x00079c14从@callee_owned(@inout Swift.UnsafemtableBufferPointer)->(@unowned(),@error@owned Swift.ErrorType)到@callee_owned(@inout Swift.UnsafemtableBufferPointer)->(@out(),@error@owned Swift.ErrorType)(NSData+Extension.Swift:0)的重新提取thunk帮助程序的部分应用转发器
8 MyAppName 0x00079cb8 Swift.Array.WithUnsafemtableBufferPointer((inout Swift.UnsafemtableBufferPointer)的泛型专门化抛出->A1)抛出->A1(NSData+扩展名。Swift:0)
9 MyAppName 0x00079a70(MyAppName中的扩展名):\uu ObjC.NSData.dataType.getter:Swift.String?(NSData+分机。swift:55)
10 MyAppName 0x00079948@objc(MyAppName中的扩展名):\uu objc.NSData.dataType.getter:Swift.String?(NSData+分机。swift:0)
11 MyAppName 0x000d2264 MyAppName.DataManager.(从服务器(MyAppName.ImageSet)->())(闭包#1)(DataManager.swift:1214)
12 libdispatch.dylib 0x218cd823——调度、呼叫、阻塞和释放+8
13 libdispatch.dylib 0x218dc5e9_dispatch_root_queue_drain+1558
14 libdispatch.dylib 0x218dbfcd_dispatch_worker_thread3+94
15 libsystem_pthread.dylib 0x21a91b29_pthread_wqthread+1022
16 libsystem_pthread.dylib 0x21a91718 start_wqthread+6
使现代化 在代码发生以下变化的情况下,仍然会发生崩溃:

// Get first byte
var c: UInt8 = 0;
self.getBytes(&c, length: 1)
// Get first byte
var c = [UInt8](count: 1, repeatedValue: 0)
c.withUnsafeMutableBufferPointer {
    buffer in
    getBytes(buffer.baseAddress, length: 1)
}

guard c.indices.contains(0) else { return nil }
// Get first byte
var c = UnsafeMutablePointer<UInt8>.alloc(1)
defer { c.dealloc(1) }
self.getBytes(c, length: 1)    

switch (c[0]) { ...
//获取第一个字节
var c=UnsafeMutablePointer.alloc(1)
延迟{c.dealoc(1)}
self.getBytes(c,长度:1)
开关(c[0]){。。。

代码> 一个快速数组更像是一个C++代码:ST::vector > C数组:除了数组元素之外,还有其他内容。不能用<代码>和c<代码>来获取第一个元素的指针。你需要向数组询问它的元素的指针,比如:

var c = [UInt8](count: 1, repeatedValue: 0)
c.withUnsafeMutableBufferPointer { buffer in
    getBytes(buffer.baseAddress, length: 1)
}

一个快速数组更像是C++代码:STD::vector > C数组:除了数组元素之外,还有其他内容。不能使用“代码>和C < /Cord>”获取第一个元素的指针。需要向数组询问其元素的指针,例如:

var c = [UInt8](count: 1, repeatedValue: 0)
c.withUnsafeMutableBufferPointer { buffer in
    getBytes(buffer.baseAddress, length: 1)
}

但是,对于您的特定情况,使用数组似乎有些过分。为什么不这样做呢:

var c: UInt8 = 0;

self.getBytes(&c, length: 1)

但是,对于您的特定情况,使用数组似乎有些过分。为什么不这样做呢:

var c: UInt8 = 0;

self.getBytes(&c, length: 1)

在一名苹果工程师的帮助下(通过TSI票据),问题最终被确定。 上述用于读取第一个字节的所有代码排列均有效且有效

问题在于,
NSData
对象是在使用从服务器获取文件时创建的,该服务器使用文件保护密钥
nsfileprotectioncompleteentilfirstureauthentication
将数据存储在临时文件中

文件保护密钥仅允许用户在重新启动后解锁设备一次后读取
NSData
对象的数据。虽然解锁前数据不可读,但可以创建
NSData
对象,甚至可以访问
NSData.length
属性。但是,尝试读取数据会引发例外

在尝试使用
UIApplication.sharedApplication().protectedDataAvailable
读取受保护的数据之前,我更改了代码并添加了一项检查,以确定受保护的数据是否可用

你可能想知道为什么在解锁设备之前应用程序就提取了一个文件。应用程序是由远程用户通知启动的。这就是为什么崩溃很少发生的原因

学到了两件事:

  • 始终检查您的文件保护密钥
  • 苹果的技术支持给出了一个超级深入的解释,而且是值得的

在一名苹果工程师的帮助下(通过TSI票据),问题最终被确定。 上述用于读取第一个字节的所有代码排列均有效且有效

问题在于,
NSData
对象是在使用从服务器获取文件时创建的,该服务器使用文件保护密钥
nsfileprotectioncompleteentilfirstureauthentication
将数据存储在临时文件中

文件保护密钥仅允许用户在重新启动后解锁设备一次后读取
NSData
对象的数据。虽然解锁前数据不可读,但可以创建
NSData
对象,甚至可以访问
NSData.length
属性。但是,尝试读取数据会引发例外

在尝试使用
UIApplication.sharedApplication().protectedDataAvailable
读取受保护的数据之前,我更改了代码并添加了一项检查,以确定受保护的数据是否可用

你可能想知道为什么在解锁设备之前,应用程序就提取了文件。应用程序是由远程用户noti启动的