91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

從YYModel源碼中可以學到什么:前篇

發布時間:2020-07-24 11:44:56 來源:網絡 閱讀:3898 作者:Owenli_千 欄目:移動開發

前言

YYModel一個高性能模型框架。

作者在Github上給出的性能對比圖(iphone 6 y:時間)

從YYModel源碼中可以學到什么:前篇

YYModel:具體以下特點:高性能、自動類型轉換、類型安全、非侵入性、輕量等。

關于如何使用YYModel查看文檔和示例【傳送門】。

本文主要任務,分析YYModel的整體架構,實現思路,涉及到的知識點。

版本:1.0.4

文件結構

從YYModel源碼中可以學到什么:前篇

YYModel,只有5個文件。接下我們會具體看這五個文件都做了什么工作。

  • YYModel.h頭文件,通過#import該文件使用庫。
  • YYClassInfo.h 根據名字應該能猜出,關于Class信息的文件。
  • NSObject + YYModel.h 這個NSObject的一個Category。還定義了一些內部類。

從YYModel源碼中可以學到什么:前篇

YYModel頭文件

該文件只是一個頭文件,代碼很少。

#if __has_include(<YYModel/YYModel.h>)
FOUNDATION_EXPORT double YYModelVersionNumber;
FOUNDATION_EXPORT const unsigned char YYModelVersionString[];
#import <YYModel/NSObject+YYModel.h>
#import <YYModel/YYClassInfo.h>
#else
#import "NSObject+YYModel.h"
#import "YYClassInfo.h"
#endif

拓展:

  1. FOUNDATION_EXPORT是用來定義常量的,另外一個經常用到的#define定義常量。

    那么兩者的區別?
    假設分別使用兩者定義字符串常量,前者可以通過==來判斷字符串是否相等,后者則需要使用isEqualToString:來判斷。因為,前者比較的是字符串指針地址,后者比較每個字符,因此前者效率更高。

  2. __has_include()

    #if __has_include(&lt;UIKit/UIKit.h&gt;)
    // 包含
    #else
    // 不包含
    #endif          
    

    判斷UIKit庫是否存在。

YYClassInfo

YYClassInfo文件中定義四個類,涉及到Runtime知識,請看這篇文章博文或者直接查看[objc4源碼]()

從YYModel源碼中可以學到什么:前篇

  • YYClassIvarInfo

    該類對應實例變量信息(ivars),包含:名稱,偏移量,類型編碼,類型;其中類型請查看【官方文檔Type Encodings】

  • YYClassMethodInfo

    方法的信息類,包含,方法名稱,SEL,IMP,參數類型編碼,返回值類型編碼等。

  • YYClassPropertyInfo

    屬性信息類,包含名稱,類型,類型編碼,ivar名稱,類,協議列表,setter/getter等。

  • YYClassInfo:類信息。

拓展

Ivar, Method, Property, SEL, IMP都是什么?

理解這些需要對runtime了解,上面給出了博文鏈接,這里簡單復習一下。

typedef struct objc_method *Method; // 方法
typedef struct objc_ivar *Ivar; // 實例變量
typedef struct objc_category *Category; //分類
typedef struct objc_property *objc_property_t; // 屬性

struct objc_class {
    Class isa 
    Class super_class // 指向父類  
    const char * name // 名稱                   
    long version                                          
    long info                                               
    long instance_size                                      
    struct objc_ivar_list * ivars // 實例變量表
    struct objc_method_list * * methodLists  //方法表                 
    struct objc_cache * cache                    
    struct objc_protocol_list * protocols //協議表 

};
/* Use `Class` instead of `struct objc_class *` */

Ivar指實例變量,存放在實例變量表中。Method方法,存放在方法表中。

接下再看一下Objc_method結構體

struct objc_method {
    SEL method_name
    char * method_types
    IMP method_imp 
    }  

SEL指方法名稱,IMP指方法實現。

NSObject + YYModel

該文件定義三個分類和一個協議,以及兩個內部類,下面是.h文件中提供的接口。

NSObject分類

提供了一些datamodel轉換的方法。

// 根據接收到JSON創建一個實例,該方法是線程安全的。
// json對象可以是 NSDictionary,NSString,NSData.
+ (nullable instancetype)yy_modelWithJSON:(id)json;

// 字典轉Model 
+ (nullable instancetype)yy_modelWithDictionary:(NSDictionary *)dictionary;

// 通過json設置屬性, 無效的數據會被忽略
- (BOOL)yy_modelSetWithJSON:(id)json;
- (BOOL)yy_modelSetWithDictionary:(NSDictionary *)dic;

// model轉json對象(NSDictionary/NSArray), NSData, NSString
- (nullable id)yy_modelToJSONObject;
- (nullable NSData *)yy_modelToJSONData;
- (nullable NSString *)yy_modelToJSONString;

#pragma mark - 其他快捷方法
// 拷貝(NSCoping協議)
- (nullable id)yy_modelCopy;

// 編碼和解碼(對應NSCoding協議的兩個方法)
- (void)yy_modelEncodeWithCoder:(NSCoder *)aCoder;
- (id)yy_modelInitWithCoder:(NSCoder *)aDecoder;

// NSObject協議
// 哈希值
- (NSUInteger)yy_modelHash;
// 相等判斷
- (BOOL)yy_modelIsEqual:(id)model;
// Debug描述
- (NSString *)yy_modelDescription;

以上NSObject分類中提供的接口,具體實現稍后學習。

// 直接添加以下代碼即可自動完成
- (void)encodeWithCoder:(NSCoder *)aCoder { [self yy_modelEncodeWithCoder:aCoder]; }
- (id)initWithCoder:(NSCoder *)aDecoder { self = [super init]; return [self yy_modelInitWithCoder:aDecoder]; }
- (id)copyWithZone:(NSZone *)zone { return [self yy_modelCopy]; }
- (NSUInteger)hash { return [self yy_modelHash]; }
- (BOOL)isEqual:(id)object { return [self yy_modelIsEqual:object]; }
- (NSString *)description { return [self yy_modelDescription]; }

NSArray分類

從json-array中創建一個數組, 其實也是遍歷循環調用字典轉Model。

+ (nullable NSArray *)yy_modelArrayWithClass:(Class)cls json:(id)json;

NSDictionary分類

從json創建字典。

+ (nullable NSDictionary *)yy_modelDictionaryWithClass:(Class)cls json:(id)json;

YYModel協議

YYModel協議,通過實現響應的方法,可以提供白名單,黑名單,自定義屬性名稱等功能。

// 自定義屬性名稱,可以將json中的名稱映射到自定義的名稱,可以解決沖突例如`id`。
+ (nullable NSDictionary<NSString *, id> *)modelCustomPropertyMapper;

// 如果屬性是一個容器對象,例如NSArray/NSSet/NSDictonary,實現該方法可以返回一個映射字典(property -> class)
+ (nullable NSDictionary<NSString *, id> *)modelContainerPropertyGenericClass;

+ (nullable Class)modelCustomClassForDictionary:(NSDictionary *)dictionary;

// 白名單和黑名單(若實現,忽略黑名單,只處理白名單)
+ (nullable NSArray<NSString *> *)modelPropertyBlacklist;
+ (nullable NSArray<NSString *> *)modelPropertyWhitelist;

- (NSDictionary *)modelCustomWillTransformFromDictionary:(NSDictionary *)dic;

// 數據驗證和自定義轉換
// 當JSON轉為Model完成后,會調用該方法。可以在該方法中進行校驗工作,返回NO該Model被忽略,也可以完成一些轉換工作。
- (BOOL)modelCustomTransformFromDictionary:(NSDictionary *)dic;
- (BOOL)modelCustomTransformToDictionary:(NSMutableDictionary *)dic;

拓展

  1. 在源碼中會發現有一對NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END宏。

    在Swift中存在Option類型,可以使用!?聲明變量,但是在OC中沒有這個特性。出現新的關鍵詞用于OC轉Swift時區分能否為空。

    nullable && nonnull

    nullable指對象可以為NULL。

    nonnull指對象不可以為NULL。

    如果不遵循這一規則,編譯器就會給出警告。

    為了簡化書寫,在NS_ASSUME_NONNULL_BEGINNS_ASSUME_NONNULL_END宏之間的代碼,默認都是nonnull。所以我們只需指定哪些nullable的指針就可以了。
    StackOverflow關于該宏的問題。

其他知識點

接下來補充一些知識點,或許對以后開發有幫助。

NS_OPTIONS && NS_ENUM

這是兩個簡單方便的宏定義,從iOS6開始,他們取代了原來的enum

例如:

typedef NS_ENUM(NSInteger, UITableViewCellStyle) {
    UITableViewCellStyleDefault,
    UITableViewCellStyleValue1,
    UITableViewCellStyleValue2,
    UITableViewCellStyleSubtitle
};

其中第一個元素存儲類型。第二個參數是名字。

另外,enum也可以被定義為按位掩碼。用簡單的OR和AND數學運算既可實現一個整型值的編碼。請看這篇文章《NS_ OPTIONS && NS _ENUM - NShipster》。

小結

本章主要整理YYModel整體框架以及開發者提供的接口,并沒有涉及到內部實現。接下來的文章,我將會一步步分析源碼實現。

參考

Github - ibireme/YYModel

個人博客Owenli
微博Owenli_千

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

巨鹿县| 郴州市| 三河市| 随州市| 小金县| 衡阳市| 社旗县| 郎溪县| 宣城市| 文化| 安塞县| 万源市| 大邑县| 旌德县| 普兰县| 广水市| 五寨县| 延津县| 特克斯县| 辉县市| 田林县| 司法| 军事| 原平市| 右玉县| 广丰县| 南平市| 崇州市| 东阿县| 南阳市| 汝州市| 富裕县| 洮南市| 尤溪县| 东港市| 麦盖提县| 独山县| 兴安县| 锡林郭勒盟| 宜君县| 白城市|