Objective-C - 從API取得List來自之我以為很簡單但往往沒那麼簡單

問題發生於從WebAPI取得結果,以Dictionary操作,再轉換成對應的Object時,取一個屬性可能是Int或String時發生以下錯誤:

Fatal Exception: NSInvalidArgumentException -[NSTaggedPointerString stringValue]: unrecognized selector sent to instance 0xa000039312f31305

原程式如下:


// Profile.h

@interface Payment : NSObject

@property (strong,nonatomic) NSString*  name;
@property (strong,nonatomic) NSString*  display_date;

@end

@interface Profile : NSObject

@property (strong,nonatomic) NSString*  id;
@property (strong,nonatomic) NSMutableArray<Payment*>* payments;

@end

// Profile.m

@implementation Payment
-(id)initWithDictionary:(NSDictionary*)dic{
    self = [super init];
    if (self) {
        self.name = dic[@"name"];
        self.display_date = dic[@"display_date"]; // exception occur!!!!
    }
}
@end

@implementation Profile
-(id)initWithDictionary:(NSDictionary*)dic{
    self = [super init];
    if (self) {
        self.id = dic[@"id"];
        if (nil != dic[@"payments"]){
            self.payments = [NSMutableArray array];
            for(NSDictionary* subDic in dic[@"payments"]){
                Payment* payment = [[Payment alloc] initWithDictionary:subDic];
                }
            }
        }
    }
    return self;
}
@end

原本的問題是因為我在下面這行發生錯誤:

        self.display_date = dic[@"display_date"]; // exception occur!!!!

查了一下發現,這個display_date可能回過來int或string,我原以為反正我用string都可以通吃,沒想到如果第一筆是int、第二筆是string時會發生錯誤

於是乎我把這行改成,取它的stringValue:

self.display_date = [dic[@"display_date"] stringValue]; // exception occur!!!!

沒想到這麼一轉,原本的問題解了,但又反過來,在第二筆時因為已經是string了,所以再轉會出錯…

好吧,那只好在轉換前先判斷能否轉換了

所以在取這種特別的欄位時,改用以下的方法取得:

-(NSString *)getDictValueWithKey:(NSString*)key fromDict(NSDictionary*):dict {

NSString * string;
if ([[dict objectForKey:key] respondsToSelector:@selector(stringValue)]) {
    string = [[dict objectForKey:key] stringValue];
}
else {
   string = [NSString stringWithString:[dict objectForKey:key]];
}
return string;
}

註:其實我在自己的開發環境是無法完美重現後面那個問題的,所以只能先預判這樣可能可以解決這個問題