简体   繁体   中英

Convert array of custom object to AnyObject in Swift

In my app I am doing something like this:

struct Record {
    var exampleData : String
}

class ExampleClass : UIViewController {
    let records = [Record]()

    override func viewDidLoad() {
        super.viewDidLoad()

        let data = NSKeyedArchiver.archivedDataWithRootObject(self.records) as! NSData
    }

    ...

}

But in the last line of viewDidLoad() I got this error:

Argument type '[Record]' does not conform to expected type 'AnyObject'

How can I fix this? Thanks.

If you want to keep struct , you can encode data using withUnsafePointer() . Here's an example, which I adapted from this Gist :

import UIKit

enum EncodingStructError: ErrorType {
    case InvalidSize
}

func encode<T>(var value: T) -> NSData {
    return withUnsafePointer(&value) { p in
        NSData(bytes: p, length: sizeofValue(value))
    }
}

func decode<T>(data: NSData) throws -> T {
    guard data.length == sizeof(T) else {
        throw EncodingStructError.InvalidSize
    }

    let pointer = UnsafeMutablePointer<T>.alloc(1)
    data.getBytes(pointer, length: data.length)

    return pointer.move()
}

enum Result<T> {
    case Success(T)
    case Failure
}

I added some error handling and marked the method as throws . Here's one way you can use it, in a docatch block:

var res: Result<String> = .Success("yeah")

var data = encode(res)

do {
    var decoded: Result<String> = try decode(data)

    switch decoded {
    case .Failure:
        "failure"
    case .Success(let v):
        "success: \(v)" // => "success: yeah"
    }
} catch {
    print(error)
}

The error handling I added will not decode if the NSData length doesn't match the type size. This can commonly happen if you write the data to disk, the user updates to a newer version of the app with a different-sized version of the same type, and then the data is read in.

Also note that sizeof() and sizeofValue() may return different values on different devices, so this isn't a great solution for sending data between devices ( NSJSONSerialization might be better for that).

AnyObject means any reference type object, primarily a class. A struct is a value type and cannot be passed to a function needing an AnyObject . Any can be used to accept value types as well as reference types. To fix your code above, change struct Record to class Record . But I have a feeling you may want to use a struct for other reasons. You can create a class wrapper around Record that you can convert to and from to use for functions that need an AnyObject .

I did a similar thing:

    static func encode<T>(value: T) -> NSData {
        var val = value
        return withUnsafePointer(to: &val) { pointer in
            NSData(bytes: pointer, length: MemoryLayout.size(ofValue: val))
        }
    }

    static func decode<T>(data: NSData) -> T {
        guard data.length == MemoryLayout<T>.size.self else {
            fatalError("[Credential] fatal unarchiving error.")
        }

        let pointer = UnsafeMutablePointer<T>.allocate(capacity: 1)
        data.getBytes(pointer, length: data.length)

        return pointer.move()
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM