3

コード全体で [de]/serialization を繰り返すのではなく、NSJSONSerializationメソッドをCategoryonにカプセル化しようとしています。NSObject

.h

#import <Foundation/Foundation.h>

@interface NSObject (AYIAdditions)

+ (NSString *)JSONString;
+ (id)objectFromJSONString;
+ (id)objectFromJSONData;

@end

ただし、次のエラーが表示されます: No visible @interface for 'NSMutableDictionary' はセレクター 'JSONString' を宣言しています

NSMutableDictionary継承NSObjectしているため、これらのカテゴリ メソッドを継承する必要があります。私は何が欠けていますか?

余談ですが、カテゴリを使用するのは良いアプローチです ( Ray Wenderlich が言及)。または、いくつかのクラス メソッドを使用してカスタム オブジェクトを作成する必要があります。

4

3 に答える 3

5

コード内:

+ (NSString *)JSONString;

(+プラス記号) は、クラス メソッドを示します。おそらく次のようなインスタンス メソッドが必要です。

- (NSString *)JSONString;

シリアライゼーションの実装方法について:これはかなりの「余談」です。あなたが求めていることの範囲は非常に広く、具体的なことはほとんどありません。これは実際には、ニーズの範囲と投資したい時間/エネルギーの関数ですが、意見を検討する必要があります。

上のカテゴリNSObjectは少し広すぎるように思えます。より論理的な選択であるプロトコルよりも良い結果が得られる可能性は低いと思います.

率直に言っNSJSONSerializationて、独自のカスタム モデル オブジェクトをシリアル化するためのプロトコルを宣言しておけばよかったと思いますNSCoding。これは、オブジェクトを にエンコードするときに私が行く一般的なルートJSONです。プロトコルは次のようになります。

NSString * const MySerializationClassKey = @"MySerializationClassKey";
@protocol MySerializationProtocol <NSObject>
@required
-(NSDictionary *)dictionarySerialization;
-(id)initFromDictionarySerialization:(NSDictionary *)dictionary;
@end

そして、カスタムモデルオブジェクトは次のようにシリアル化および逆シリアル化できます:(非常に単純化されています)

@interface MyModel() <MySerializationProtocol>
@property (strong) NSString *name;
@end
@implementation MyModel
NSString * const MyModelNameKey = @"MyModelNameKey";
@synthesize name = _name;
-(NSDictionary *)dictionarySerialization{
    // encode object as dictionary
    return @{MySerializationClassKey: NSStringFromClass(self.class), MyModelNameKey: _name.copy};
}
-(id)initFromDictionarySerialization:(NSDictionary *)dictionary{
    if ((self = [super init])){
        _name = [dictionary objectForKey:MyModelNameKey];
    }
    return self;
}
@end

NSArrayここで、完全なシリアル化ライブラリを回答に入力しないために、これらのモデル オブジェクトのフラットしかなかったとします。NSJSONSerializationこれらのメソッドと連携して使用するクラスを作成できます。各呼び出しを簡単にするには、次のようにします。

@interface MySerializer : NSObject
@end
@implementation MySerializer
+(NSData *)jsonDataFromObject:(NSMutableArray *)array{
    for (NSUInteger index = 0; index < array.count; index++) {
        NSObject *object = [array objectAtIndex:index];
        if ([object conformsToProtocol:@protocol(MySerializationProtocol)]){
            NSDictionary *dictRep = [(id<MySerializationProtocol>)object dictionarySerialization];
            [array replaceObjectAtIndex:index withObject:dictRep];
        }
    }
    return [NSJSONSerialization dataWithJSONObject:array options:0 error:nil];
}
+(NSMutableArray *)objectFromJSONData:(NSData *)data{
    NSMutableArray *array = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
    for (NSUInteger index = 0; index < array.count; index++) {
        NSObject *object = [array objectAtIndex:index];
        if ([object isKindOfClass:[NSDictionary class]]){
            NSDictionary *dict = (NSDictionary *)object;
            NSString *className = [dict objectForKey:MySerializationClassKey];
            if (className.length > 0) {
                NSObject *deserialized = [[NSClassFromString(className) alloc] initFromDictionarySerialization:dict];
                if (deserialized) [array replaceObjectAtIndex:index withObject:deserialized];
            }
        }
    }
    return array;
}
@end

明らかに、このようなコードからマイレージを取得するには、可能な配列と辞書を再帰的にトラバースする必要があります。しかし、これは私の好みのルートです。

于 2013-03-27T18:20:46.537 に答える
0

カテゴリのヘッダーをインポートしたことは確かですか?

#import "NSObject+AYIAdditions.h"

これが正しいアプローチであるかどうかは議論の余地があります。すべてのオブジェクトで呼び出すことができないメソッドを追加するのは良い解決策ではないと思いNSObjectます (すべてのオブジェクトを JSON シリアル化できるわけではありません)。

于 2013-03-27T18:14:21.263 に答える
0

NSJSONSerialization クラスを使用して、JSON を Foundation オブジェクトに変換し、Foundation オブジェクトを JSON に変換します。

JSON に変換できるオブジェクトには、次のプロパティが必要です。

  • 最上位オブジェクトは NSArray または NSDictionary です。
  • すべてのオブジェクトは、NSString、NSNumber、NSArray、NSDictionary、または NSNull のインスタンスです。
  • すべての辞書キーは NSString のインスタンスです。
  • 数値は NaN または無限大ではありません。他の規則が適用される場合があります。

変換の呼び出しisValidJSONObject:または試行は、特定のオブジェクトを JSON データに変換できるかどうかを確認する決定的な方法です。ソース: Apple のドキュメント

そのため、NSObject でそのカテゴリを定義する必要があります。意味のある場所は NSArray と NSDictionary です。

sharedSerializerまた、両方のカテゴリから呼び出される を提供するシリアライザ クラスも作成します。


別のアプローチとして、実際に NSObject でカテゴリを宣言することもできますが、n 個のオブジェクトをシリアル化できなかったケースを処理するために失敗ブロックを渡します。

于 2013-03-27T18:36:12.543 に答える