2014-06-14 17 views
6

trong Objective-C, tôi đang sử dụng các mã sau để tuần tự hóa một lớp tùy chỉnh thành một từ điển hoạt động tốt. Để làm quen với Swift, hãy chuyển mã Objective-C sang Swift. Tuy nhiên tôi không thể đạt được điều này, làm thế nào để làm điều này với Swift?làm cách nào để nối tiếp NSDictionary từ một Class - Swift thực hiện

đây là cách tôi đạt được với Objective-C

.h 
#import <Foundation/Foundation.h> 
#import <objc/runtime.h> 

@interface NSObject (aClass_NSDictionary) 
- (NSDictionary *)NSDictionaryFromClass; 
@end 

.m 
@implementation NSObject (aClass_NSDictionary) 

- (NSDictionary *)NSDictionaryFromClass { 

    Class aClass = [self class]; 
    u_int propertiesCount; 

    objc_property_t *propertiesInAClass = class_copyPropertyList(aClass, &propertiesCount); 

    NSMutableDictionary *propertiesDictionary = [[NSMutableDictionary alloc] initWithCapacity:propertiesCount]; 

    for (int i = 0; i < propertiesCount; i++) 
    { 
     NSString *strAKey = [NSString stringWithCString:property_getName(propertiesInAClass[i]) 
               encoding:NSUTF8StringEncoding]; 

     [propertiesDictionary setValue:[self valueForKey:strAKey] 
           forKey:strAKey]; 
    } 
    free(propertiesInAClass); 
    return propertiesDictionary; 
} 
@end 

khi tôi viết cùng mã trong nhanh chóng tôi không thể quản lý để tìm hiểu tương đương với [self class].

class class2dicti : NSObject { 

    class func nsdictionaryFromAClass() -> NSDictionary { 

     let aClass = self.classForCoder 
     var propertiesCount : u_int 
     let propertiesInAClass : objc_property_t = class_copyPropertyList(aClass, &propertiesCount) 

     //return NSDictionary() 
    } 
} 

Cập nhật

cho đến nay tôi đã cố gắng:

let aClass = self.classForCoder 
    var propertiesCount : u_int 
    let propertiesInAClass : objc_property_t = class_copyPropertyList(aClass, &propertiesCount) 

let aClass : AnyClass! = self.classForCoder() 

không thành công, vẫn cùng một trình biên dịch báo lỗi "Không thể tìm thấy một tình trạng quá tải cho '__conversion' chấp nhận các đối số được cung cấp "

Giải pháp

liên quan đến câu trả lời bên dưới Tôi đã tìm thấy giải pháp này và nó đã hoạt động. Về cơ bản tôi đã tạo ra phần mở rộng cho lớp học của tôi.

class myClass : NSObject { 
    var propertyOne = "prop One" 
    var propertyTwo = [1, 2, 3] 
    var propertyThree = ["A":1, "B":2, "C":3] 
} 

extension myClass { 
    func toDictionary() -> NSDictionary { 

     var aClass : AnyClass? = self.dynamicType 
     var propertiesCount : CUnsignedInt = 0 
     let propertiesInAClass : UnsafePointer<objc_property_t> = class_copyPropertyList(aClass, &propertiesCount) 

     var propertiesDictionary : NSMutableDictionary = NSMutableDictionary() 

     for var i = 0; i < Int(propertiesCount); i++ { 
      var strKey : NSString? = NSString(CString: property_getName(propertiesInAClass[i]), encoding: NSUTF8StringEncoding) 
      propertiesDictionary.setValue(self.valueForKey(strKey), forKey: strKey) 
     } 
     return propertiesDictionary 
    } 
} 

giờ đây let myclazz = myClass().toDictionary() mang lại cho tôi NSDictionary. tất cả các đề xuất đều được hoan nghênh.

+0

bạn đã thử 'self.classForCoder' chưa? – Firo

+0

let aClass: AnyClass! = self.classForCoder() cho tôi "Không thể tìm thấy quá tải cho '__conversion' chấp nhận đối số được cung cấp" – mohacs

+0

xóa '()' nó phải là 'self.classForCoder' mà không có dấu ngoặc đơn. 'classForCoder' là thuộc tính. Bạn có thể 'classForCoder()' như là một phương thức lớp trên một lớp (không phải là một cá thể) ('MyClass.classForCoder()') – Firo

Trả lời

1

Trong Swift bạn không bao giờ làm việc với các lớp học. Bạn làm việc với các loại:

var clazz: AnyClass? = self.dynamicType 
class_copyPropertyList(clazz, nil) 

Tất cả phương pháp Obj-C trả về Class, ví dụ: classForCoder được cập nhật để trả về loại Swift thay thế (AnyClass).

Lưu ý rằng bạn có vấn đề kiểu khác đó:

var propertiesCount : CUnsignedInt = 0 
let propertiesInAClass : UnsafePointer<objc_property_t> = class_copyPropertyList(clazz, &propertiesCount) 

Nếu bạn thực sự cần phải truy cập vào các lớp obj-C như AnyObject, ví dụ để tạo ra một loạt các lớp học và vượt qua nó để obj-C, xem this

+0

self.dynamicType đã giúp xây dựng giải pháp của tôi. – mohacs

0

Tôi đang sử dụng cách này lưu trữ mọi thứ tuân theo giao thức NSCoding.

trước tiên tôi lấy URL cho thư mục, ví dụ: ví dụ: Documents thư mục:

var error: NSError? 
let documentURL : NSURL = NSFileManager.defaultManager().URLForDirectory(NSSearchPathDirectory.DocumentDirectory, inDomain: NSSearchPathDomainMask.UserDomainMask, appropriateForURL: nil, create: true, error: &error) 

sau đó tôi sau đó giải nén vào thư mục đó:

let object: AnyObject = // ... 
let filename: String = "<filename>" 
let customExtension: String = "<extension>" 
let urlForFile: NSURL = documentURL.URLByAppendingPathComponent(filename).URLByAppendingPathExtension(customExtension) 
let result: Bool = NSKeyedArchiver.archivedDataWithRootObject(object).writeToURL(urlForFile, atomically: true) 

và hủy lưu trữ sau đó là khá giống với cách gần đây:

let data: NSData = NSData.dataWithContentsOfFile(urlForFile.path, options: NSDataReadingOptions.DataReadingUncached, error: &error) 
let object: AnyObject = NSKeyedUnarchiver.unarchiveObjectWithData(data) 

LƯU Ý: đó là một ví dụ thô, mà không kiểm tra bất cứ điều gì cho dù đó lànilhoặc xử lý lỗi có thể xảy ra. bạn có thể cần phải thêm chúng cho mã cuối cùng của bạn.

0

Tôi đã viết thư viện c mục tiêu tự động thực hiện việc này dựa trên các giá trị khóa và tên thuộc tính. Tôi có một chi nhánh để hỗ trợ các lớp học Swift và nó hoạt động tốt. https://github.com/aryaxt/OCMapper

2

Đây là cách tôi triển khai tuần tự hóa sâu.

Nếu thuộc tính là DictionarySerializedObject thì nó được sắp xếp theo thứ tự đệ quy.

Hãy cẩn thận vì class_copyPropertyList() không trả lại thuộc tính của các loại Swift tùy chọn như Bool?, [String?] vì Foundation không cung cấp cầu cho chúng. Ví dụ: nó cung cấp cầu nối cho Bool đến NSNumber nhưng không cung cấp cầu nối cho Bool?.

import Foundation 

protocol DictionarySerializable { 
    func serializeToDictionary() -> [String:AnyObject] 
} 

class DictionarySerializableObject: NSObject { 
} 

extension NSObject: DictionarySerializable { 
    func serializeToDictionary() -> [String:AnyObject] { 
     var aClass: AnyClass? = self.dynamicType 
     var propertiesCount: CUnsignedInt = 0 
     let properties = class_copyPropertyList(aClass, &propertiesCount) 
     var dictionary = [String: AnyObject]() 
     for var i = 0; i < Int(propertiesCount); i++ { 
      if let name = NSString(CString: property_getName(properties[i]), encoding: NSUTF8StringEncoding) as? String { 
       dictionary[name] = getDictionaryValueForObject(self.valueForKey(name)) 
      } 
     } 
     free(properties) 
     return dictionary 
    } 

    private func getDictionaryValueForObject(object: AnyObject?) -> AnyObject { 
     if let object: AnyObject = object { 
      if let object = object as? DictionarySerializableObject { 
       return object.serializeToDictionary() 
      } else if let object = object as? [AnyObject] { 
       var array = [AnyObject]() 
       for item in object { 
        array.append(getDictionaryValueForObject(item)) 
       } 
       return array 
      } else if let object = object as? NSData { 
       return object.base64EncodedStringWithOptions(NSDataBase64EncodingOptions(0)) 
      } else { 
       return object 
      } 
     } else { 
      return NSNull() 
     } 
    } 
} 
Các vấn đề liên quan