如何在 Mantle 中声明可选属性?

Posted

技术标签:

【中文标题】如何在 Mantle 中声明可选属性?【英文标题】:How to declare optional property in Mantle? 【发布时间】:2017-08-27 07:20:08 【问题描述】:

具体情况详解:

在我目前的拍照应用中,有这样的情况:先让用户体验,无需登录, 但从后端响应的 JSON 中没有某些字段(例如:已投票、已购买等)。如果用户登录, 该字段以 JSON 格式添加。

我将展示我的实现细节如下:

PhotoListResponseModel(直接继承MTLModel)

@interface PhotoListResponseModel : MTLModel <MTLJSONSerializing>
...
@property (nonatomic, copy, readonly) NSNumber *foo;
@property (nonatomic, copy, readonly) NSArray<PhotoModel *> *subPhotos;

@end

@interface PhotoModel : MTLModel <MTLJSONSerializing>

@property (nonatomic, copy, readonly) NSNumber *photoID;
@property (nonatomic, copy, readonly) NSURL *imageUrl;
...
@end


@implementation PhotoListResponseModel
+ (NSDictionary *)JSONKeyPathsByPropertyKey 
   return @@"foo": @"foo"
            @"subPhotos": @"photos"
            ;


+ (NSValueTransformer *)subPhotosJSONTransformer 
    return [MTLJSONAdapter arrayTransformerWithModelClass:PhotoModel.class];


@end

@implementation PhotoModel
+ (NSDictionary *)JSONKeyPathsByPropertyKey 
    return @
             @"photoID": @"id",
             @"userID": @"user_id",
             ;


@end

相应地,JSON 示例如下:

noAuthPhoto.json


        "foo": 1,
        "photos": [
                   
                   "id": 204748881,
                   "image_url": "https://foo1/bar1",
                   ,
                   
                   "id": 204996257,
                   "image_url": "https://foo2/bar2"
                   
                   ],
                   …
                   …
    

AuthedPhoto.json


        "foo": 1,
        "photos": [
                   
                   "id": 204748881,
                   "image_url": "https://foo1/bar2”,
                   "voted": false,
                   "purchased": false
                   ,
                   
                   "id": 204996257,
                   "image_url": "https://foo2/bar2”,
                   "voted": false,
                   "purchased": false
                   
                 ],
                 ...
                 ...
    

那么,如何让新字段兼容我已有的代码

可选属性? (我不知道该怎么做。)

或者添加继承自 PhotoListResponseModel & PhotoModel 的子类?

或者任何好主意:)


更新:我注意到this information,但仍然不知道该怎么做。

【问题讨论】:

【参考方案1】:

可选属性仅在 Swift 中可用,但对于 Obj-C 的类似想法——可能具有 nil 值的对象——应该可以很好地工作。您可以将以下NSNumber 属性添加到您的PhotoModel

@property (nonatomic, strong) NSNumber *voted;
@property (nonatomic, strong) NSNumber *purchased;

并在 PhotoModel 对象创建期间从解析的 JSON 中分配您的 BOOL 值,如下所示:

photoModelObject.voted = [NSNumber numberWithBool:[parsedJson valueForKey:@"voted"]];
photoModelObject.purchased = [NSNumber numberWithBool:[parsedJson valueForKey:@"purchased"]];

接下来,当您引用您的照片对象时,只需检查这些属性是否具有nil 值。如果他们是 - 您的用户没有登录,您不需要显示他们。否则,像这样从它们中提取 BOOL 值:

if (photoModelObject.voted && photoMobelObject.purchased) 
    BOOL isVoted = [photoModelObject.voted boolValue];
    BOOL isPurchased = [photoModelObject.purchased boolValue];

    // Use booleans to present info for registered users
 else 
    // There is no info about votes and purchasing provided for the current user

【讨论】:

照你说的让我试试 @0xDatou 请检查更新版本,我修复了一个小问题:必须使用 strong 声明属性,而不是 assign 所有权限定符。 虽然接受了答案,但我认为不应该用strong来声明。 @0xDatou NSNumber,作为一个对象,必须声明为strongweak,具体取决于您的最终目标,但肯定不是assign。否则,即使你把它放在那里,你也永远不会得到你的布尔值。相关问题:***.com/questions/11013587/… @0xDatou strong 在您的特定情况下参考是最安全的选择,没有任何负面影响。

以上是关于如何在 Mantle 中声明可选属性?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 JavaScript 中声明可选函数参数? [复制]

如何在接口中声明可选的泛型类型?

如何重新声明核心模型属性类型而不在 Hybris 中扩展它

在 mantle、dx 和 ogl 上的表现

如何在 Swift 上为堆栈声明“如果可选”

如果 XML 声明和 DTD 都是 XML 文档有效性和格式良好的先决条件,那么它们如何在规范中都是可选的?