本地購(gòu)物車 + CoreData + MagicalRecord

最近公司開發(fā)一款新的電商類的app,所以自己整理了一套購(gòu)物車的業(yè)務(wù)邏輯,提供以后的復(fù)習(xí)和整理(這里討論的只是對(duì)購(gòu)物車信息進(jìn)行本地的存儲(chǔ),未考慮后臺(tái)存儲(chǔ)的情況)。

數(shù)據(jù)存儲(chǔ)框架(Core Data)

在這里使用的是蘋果提供的Core Data,這里不去討論如何使用和優(yōu)缺點(diǎn)問題,個(gè)人覺得對(duì)于移動(dòng)端來說,并不需要大型網(wǎng)站的高并發(fā),所以這點(diǎn)性能差別幾乎是沒有影響的。

對(duì)數(shù)據(jù)讀寫(MagicalRecord)

這里對(duì)數(shù)據(jù)庫(kù)的讀寫使用一個(gè)非常不錯(cuò)的輪子:MagicalRecord(當(dāng)然也可以自己寫一套讀寫數(shù)據(jù)庫(kù)的工具類出來,思路基本都是差不多的)。github地址:https://github.com/magicalpanda/MagicalRecord

購(gòu)物車的功能和實(shí)現(xiàn)思路

功能:

    1. 登錄/未登錄狀態(tài)都可以對(duì)購(gòu)物車中的商品進(jìn)行增刪改查;
    1. 用戶登錄后,需要把未登錄時(shí)選購(gòu)的商品轉(zhuǎn)移到該用戶名下,并清空未登錄時(shí)的購(gòu)物車信息;
    1. 更新了數(shù)據(jù)庫(kù)中的購(gòu)物車數(shù)據(jù),及時(shí)的通知到用戶。

思路

  • 首先,我們得知道這個(gè)購(gòu)物車是屬于誰(shuí)的,每個(gè)登錄用戶都會(huì)有一個(gè)唯一的標(biāo)識(shí)符(ID),所以我們就把它作為購(gòu)物車的標(biāo)識(shí)符(ID),未登錄的情況我們可以定義一個(gè)固定的標(biāo)識(shí)符。
  • 購(gòu)物車中的信息是由一家家商鋪和商鋪中被選中的商品構(gòu)成的集合,所以我們可以于商鋪?zhàn)鳛橘?gòu)物車中的一個(gè)個(gè)單元,商鋪的ID就是單元的ID。
  • 我們對(duì)購(gòu)物車的轉(zhuǎn)移就是在用戶不同狀態(tài)之間的處理,對(duì)購(gòu)物車的更新實(shí)際就是對(duì)商鋪信息的更新,這樣的我們的業(yè)務(wù)邏輯就清晰了。

類的設(shè)計(jì)

涉及到的類

請(qǐng)不要在意項(xiàng)目中的類命名,我們看思路就行了 >v<

  • 模型和類的介紹
// 信息存儲(chǔ)模型

ShopModel : 商鋪信息模型類
NewGoodsModel : 商品信息模型類 

// 購(gòu)物車視圖模型

JYGoodsCartViewModel : 用戶所選商品信息(包括商品信息和購(gòu)買的數(shù)量等)
JYShopCartViewModel : 用戶在此商鋪中選購(gòu)的信息(包括商鋪信息、用戶所選的商品信息),即購(gòu)物車的組成單元。
 
// CoreData中的存儲(chǔ)模型
 
JYGoodsCart : 商品信息在CoreData中的存儲(chǔ)模型
JYShopCart : 數(shù)據(jù)庫(kù)中存儲(chǔ)的單元,即購(gòu)物車在Core Data對(duì)應(yīng)的模型類

// 工具類

JYShopCartHelper : 對(duì)數(shù)據(jù)庫(kù)進(jìn)行增刪改查的工具類,并兼具把CoreData模型轉(zhuǎn)換成購(gòu)物車的視圖模型
  • 關(guān)系圖


    關(guān)系圖

主要類的實(shí)現(xiàn)

ShopModel

  • ShopModel.h
@interface ShopModel : NSObject 

@property (nonatomic, copy) NSString *dmId;           // 店鋪ID
@property (nonatomic, copy) NSString *businessName;   // 店鋪名稱  

@end

  • ShopModel.m

因?yàn)樾枰獙?duì)模型進(jìn)行復(fù)制和歸檔解檔操作,所以需要實(shí)現(xiàn)以下方法:

@interface ShopModel () <NSCoding> 
@end

@implementation ShopModel

#pragma mark - <NSCopying>

- (id)copyWithZone:(nullable NSZone *)zone {
    ShopModel *model   = [[[self class] alloc] init];
    model.dmId         = [self.dmId copy];
    model.businessName = [self.businessName copy];  
    return model;
}

#pragma mark - encode

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.dmId forKey:@"dmId"];                         
    [aCoder encodeObject:self.businessName forKey:@"businessName"];         
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        self.dmId         = [aDecoder decodeObjectForKey:@"dmId"];
        self.businessName = [aDecoder decodeObjectForKey:@"businessName"]; 
    }
    return self;
} 

@end

NewGoodsModel

(這里展示的只是一部分屬性)

  • NewGoodsModel.h
@interface NewGoodsModel : NSObject 
         
@property (nonatomic,   copy) NSString *goodsId;        // 商品ID
@property (nonatomic,   copy) NSString *businessId;     // 商鋪ID
@property (nonatomic,   copy) NSString *goodsName;      // 商品名稱
@property (nonatomic, assign) double price;             // 價(jià)格

@end
  • NewGoodsModel.m
#pragma mark - encode

- (void)encodeWithCoder:(NSCoder *)aCoder { 
    [aCoder encodeObject:self.goodsId forKey:@"goodsId"];               // 商品ID
    [aCoder encodeObject:self.businessId forKey:@"businessId"];         // 商鋪ID
    [aCoder encodeObject:self.goodsName forKey:@"goodsName"];           // 商品名稱 
    [aCoder encodeObject:@(self.price) forKey:@"price"];                // 價(jià)格 
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) { 
        self.goodsId    = [aDecoder decodeObjectForKey:@"goodsId"];
        self.businessId = [aDecoder decodeObjectForKey:@"businessId"];
        self.goodsName  = [aDecoder decodeObjectForKey:@"goodsName"]; 
        self.price      = [[aDecoder decodeObjectForKey:@"price"] doubleValue]; 
    }
    return self;
}

@end

JYShopCartViewModel & JYGoodsCartViewModel

  • JYShopCartViewModel.h
@class ShopModel, NewGoodsModel;

@interface JYGoodsCartViewModel : NSObject

@property (nonatomic, strong) NewGoodsModel *goodsModel;    // 用戶選購(gòu)的商品
@property (nonatomic, assign) NSUInteger quantity;          // 用戶選中商品的數(shù)量

@end

 
/////////////////// 華麗的分割線 /////////////////////////////

@interface JYShopCartViewModel : NSObject

@property (nonatomic, strong) ShopModel *shopModel;                          // 商家信息
@property (nonatomic, strong) NSArray<JYGoodsCartViewModel *> *goodsArray;   // 用戶在當(dāng)前商家所選購(gòu)的所有商品集合
@property (nonatomic, strong) NSDate *createTime;                            // 添加到購(gòu)物車的時(shí)間
@property (nonatomic, strong) NSDate *updateTime;                            // 更新時(shí)間

@end 

JYShopCart

注意點(diǎn):

用@dynamic修飾屬性,是告訴編譯器,其getter和setter方法會(huì)在程序運(yùn)行的時(shí)候或者用其他方式動(dòng)態(tài)綁定,以便讓編譯器通過編譯,Core Data框架會(huì)在程序運(yùn)行的時(shí)候?yàn)榇祟悓傩陨蒰etter和Setter方法。

  • JYShopCart對(duì)應(yīng)的CoreData結(jié)構(gòu)示意圖:


    JYShopCart.png
  • JYShopCart.h

#import <CoreData/CoreData.h>

@interface JYShopCart : NSManagedObject

@property (nonatomic, copy) NSString *cartID;           // 唯一標(biāo)識(shí),其實(shí)商鋪的標(biāo)識(shí)
@property (nonatomic, copy) NSString *userID;           // 用戶標(biāo)識(shí)
@property (nonatomic, strong) id shopModel;             // 商鋪信息
@property (nonatomic, strong) NSData *goodsArrayData;   // 所選商品信息集合
@property (nonatomic, strong) NSDate *createTime;       // 添加到購(gòu)物車的時(shí)間
@property (nonatomic, strong) NSDate *updateTime;       // 更新時(shí)間

/**
 *  給當(dāng)前的購(gòu)物車更新信息
 *  
 *  shopCart: 新購(gòu)物車信息
 */
- (JYShopCart *)copyInfoByShopCart:(JYShopCart *)shopCart;

@end
  • JYShopCart.m
@implementation JYShopCart

/**
 用@dynamic修飾屬性,是告訴編譯器,其getter和setter方法會(huì)在程序運(yùn)行的時(shí)候或者用其他方式動(dòng)態(tài)綁定,以便讓編譯器通過編譯,Core Data框架會(huì)在程序運(yùn)行的時(shí)候?yàn)榇祟悓傩陨蒰etter和Setter方法。
 */
@dynamic cartID;
@dynamic userID;
@dynamic shopModel;
@dynamic goodsArrayData;
@dynamic createTime;
@dynamic updateTime;
 
#pragma mark - actions

- (JYShopCart *)copyInfoByShopCart:(JYShopCart *)shopCart {
    self.cartID         = [shopCart.cartID copy];
    self.userID         = [shopCart.userID copy];
    self.shopModel      = [shopCart.shopModel copy];
    self.goodsArrayData = [shopCart.goodsArrayData copy];
    self.createTime     = [shopCart.createTime copy];
    self.updateTime     = [shopCart.updateTime copy];
    return self;
}

@end

JYGoodsCart

  • JYGoodsCart.h
@interface JYGoodsCart : NSObject

@property (nonatomic, copy) NSString *goodsID;      // 商品標(biāo)識(shí)
@property (nonatomic, assign) NSUInteger quantity;  // 用戶選購(gòu)的商品數(shù)量
@property (nonatomic, strong) NSData *goodsData;    // 商品信息

@end
  • JYGoodsCart.m
@implementation JYGoodsCart

#pragma mark - encode

- (void)encodeWithCoder:(NSCoder *)aCoder {
    [aCoder encodeObject:self.goodsID forKey:@"goodsID"];
    [aCoder encodeObject:@(self.quantity) forKey:@"quantity"];
    [aCoder encodeObject:self.goodsData forKey:@"goodsData"];
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder {
    if (self = [super init]) {
        self.goodsID   = [aDecoder decodeObjectForKey:@"goodsID"];
        self.quantity  = [[aDecoder decodeObjectForKey:@"quantity"] integerValue];
        self.goodsData = [aDecoder decodeObjectForKey:@"goodsData"];
    }
    return self;
}

@end

JYShopCartViewModel工具類

負(fù)責(zé)對(duì)數(shù)據(jù)庫(kù)的增刪改查;

數(shù)據(jù)模型之間的轉(zhuǎn)換;

更新完數(shù)據(jù)庫(kù)后及時(shí)的通知用戶。

  • JYGoodsCart.h
@class JYShopCartViewModel;

UIKIT_EXTERN NSString * const kObserverShopCartDidChange;

@interface JYShopCartHelper : NSObject

+ (instancetype)shareShopCartHelper;

// 查詢
- (NSMutableArray *)loadShopCartInLocal;
- (JYShopCartViewModel *)checkShopCartInLocalWithShopID:(NSString *)shopID;

// 添加
- (void)addGoodsToLocalWithShopCartViewModel:(JYShopCartViewModel *)shopCartViewModel;
- (void)transformShopCartUnLoginToLoginInLocal;

// 更新
- (void)updateGoodsInLocalWithShopCartViewModel:(JYShopCartViewModel *)shopCartViewModel;

// 刪除
- (void)deleteGoodsInLocalWithGoodsArray:(NSArray *)goodsArray shopID:(NSString *)shopID;
- (void)deleteGoodsInLocalWithShopCartViewModel:(JYShopCartViewModel *)shopCartViewModel;
- (void)deleteAllGoodsInLocal;

  • JYGoodsCart.m
NSString * const kObserverShopCartDidChange = @"ObserverShopCartDidChange";

static NSString *kUnLoginUserID = @"UnLoginUserID";         // 未登錄的情況下的用戶標(biāo)識(shí),只用于購(gòu)物車中
static NSString *kShowInfo      = @"商家信息不全,添加失敗。";

@implementation JYShopCartHelper

+ (instancetype)shareShopCartHelper {
    static id shareShopCartHelper = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shareShopCartHelper = [[[self class] alloc] init];
    });
    return shareShopCartHelper;
}

#pragma mark - 查新購(gòu)物車中的所有商品

// 根據(jù)用戶ID查詢數(shù)據(jù)庫(kù)信息,返回改用戶的購(gòu)物車信息
- (NSMutableArray *)loadShopCartInLocal {
    NSArray *shopCarts = [self checkShopCartsByUserIDInLocalWithUserID:[self userIDByLogin]];
    NSArray *shopCartViewModels = [self transformShopCartsToShopCartViewModels:shopCarts];
    return [self sortShopsByCreateTimeOfShopCartWithShopCarts:shopCartViewModels];
}

// 根據(jù)店鋪ID和用戶ID,查詢改店鋪在購(gòu)物車中的選購(gòu)信息
- (JYShopCartViewModel *)checkShopCartInLocalWithShopID:(NSString *)shopID {
    JYShopCart *shopCart = [self checkShopCartInLocalWithShopID:shopID userID:[self userIDByLogin]];
    return [self transformShopCartToShopCartViewModel:shopCart];
}

// 用戶可以選擇按時(shí)間的排序類型
- (NSMutableArray *)sortShopsByCreateTimeOfShopCartWithShopCarts:(NSArray *)shopCarts {
    NSArray *sorts = [shopCarts sortedArrayUsingComparator:^NSComparisonResult(id  _Nonnull obj1, id  _Nonnull obj2) {
        JYShopCartViewModel *model1 = obj1;
        JYShopCartViewModel *model2 = obj2;
        // 根據(jù)更新時(shí)間排序,倒敘
        if (model1.updateTime == [model1.updateTime earlierDate:model2.updateTime]) {
            return NSOrderedDescending; // 降序
        } else if (model1.updateTime == [model1.updateTime laterDate:model2.updateTime]) {
            return NSOrderedAscending;  // 升序
        } else {
            return NSOrderedSame;       // 相等
        }
    }];
    return [sorts mutableCopy];
}

// 根據(jù)用戶ID,查詢數(shù)據(jù)庫(kù)信息
- (NSArray *)checkShopCartsByUserIDInLocalWithUserID:(NSString *)userID {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.userID == %@", userID];
    return [JYShopCart MR_findAllWithPredicate:predicate];
}

// 根據(jù)商鋪ID和用戶ID,查詢數(shù)據(jù)庫(kù)信息
- (JYShopCart *)checkShopCartInLocalWithShopID:(NSString *)shopID userID:(NSString *)userID {
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF.cartID == %@ && SELF.userID == %@", shopID, userID];
    return [JYShopCart MR_findFirstWithPredicate:predicate];
}


#pragma mark - 添加商品到購(gòu)物車

- (void)addGoodsToLocalWithShopCartViewModel:(JYShopCartViewModel *)shopCartViewModel {
    if (!shopCartViewModel.shopModel || shopCartViewModel.shopModel.dmId.length <= 0) {
        [SVProgressHUD showInfoWithStatus:kShowInfo];
        return;
    }
    
    JYShopCart *shopCart = [self checkShopCartInLocalWithShopID:shopCartViewModel.shopModel.dmId userID:[self userIDByLogin]];
    if (!shopCart) {
        shopCart = [JYShopCart MR_createEntity];
    } else {}
    
    shopCart.userID         = [self userIDByLogin];
    shopCart.cartID         = shopCartViewModel.shopModel.dmId;
    shopCart.shopModel      = shopCartViewModel.shopModel;
    shopCart.goodsArrayData = [self archivedDataWithGoodsArray:shopCartViewModel.goodsArray];
    shopCart.updateTime     = [NSDate date];
    shopCart.createTime     = [NSDate date];
    
    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
    [self postNotificationAfterShopCartIsChange];
}

// 未登錄選購(gòu)的商品 ===> 用戶登錄后的購(gòu)物車中
- (void)transformShopCartUnLoginToLoginInLocal {
    NSArray *shopCarts = [self checkShopCartsByUserIDInLocalWithUserID:kUnLoginUserID];
    for (JYShopCart *cart in shopCarts) {
        cart.userID = [self userIDByLogin];
    }
    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
    [self deleteAllShopCartInLocalWithUserID:kUnLoginUserID];
    [self postNotificationAfterShopCartIsChange];
}

#pragma mark - 更新購(gòu)物車中的商品

- (void)updateGoodsInLocalWithShopCartViewModel:(JYShopCartViewModel *)shopCartViewModel {
    if (!shopCartViewModel.shopModel || shopCartViewModel.shopModel.dmId.length <= 0) {
        [SVProgressHUD showInfoWithStatus:kShowInfo];
        return;
    }
    
    [self addGoodsToLocalWithShopCartViewModel:shopCartViewModel];
    [self postNotificationAfterShopCartIsChange];
}

#pragma makrk - 刪除購(gòu)物車中的商品

// 從購(gòu)物車中,刪除店鋪中的商品集合
- (void)deleteGoodsInLocalWithGoodsArray:(NSArray *)goodsArray shopID:(NSString *)shopID {
    if (shopID.length <= 0 || goodsArray.count <= 0) {
        return;
    }
    
    JYShopCartViewModel *shopCartViewModel = [self checkShopCartInLocalWithShopID:shopID];
    NSMutableArray *newGoodsArray = [shopCartViewModel.goodsArray mutableCopy];
    for (JYGoodsCartViewModel *deleteGoods in goodsArray) {
        for (JYGoodsCartViewModel *goods in shopCartViewModel.goodsArray) {
            if ([deleteGoods.goodsModel.goodsId isEqualToString:goods.goodsModel.goodsId]) {
                [newGoodsArray removeObject:goods];
            }
        }
    }
    
    if (newGoodsArray.count <= 0) {
        [self deleteShopCartInLocalWithShopID:shopID UserID:[self userIDByLogin]];
    } else {
        shopCartViewModel.goodsArray = [newGoodsArray copy];
        [self updateGoodsInLocalWithShopCartViewModel:shopCartViewModel];
    }
}

// 刪除購(gòu)物車中,此商鋪的信息
- (void)deleteGoodsInLocalWithShopCartViewModel:(JYShopCartViewModel *)shopCartViewModel {
    if (!shopCartViewModel.shopModel || shopCartViewModel.shopModel.dmId.length <= 0) {
        [SVProgressHUD showInfoWithStatus:kShowInfo];
        return;
    }
    
    [self deleteShopCartInLocalWithShopID:shopCartViewModel.shopModel.dmId UserID:[self userIDByLogin]];
    [self postNotificationAfterShopCartIsChange];
}

// 清空購(gòu)物車
- (void)deleteAllGoodsInLocal {
    [self deleteAllShopCartInLocalWithUserID:[self userIDByLogin]];
    [self postNotificationAfterShopCartIsChange];
}

- (void)deleteAllShopCartInLocalWithUserID:(NSString *)userID {
    NSArray *localShopCarts = [self checkShopCartsByUserIDInLocalWithUserID:userID];
    for (JYShopCart *cart in localShopCarts) {
        [cart MR_deleteEntity];
    }
    [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
}

- (void)deleteShopCartInLocalWithShopID:(NSString *)shopID UserID:(NSString *)userID {
    JYShopCart *shopCart = [self checkShopCartInLocalWithShopID:shopID userID:userID];
    if (shopCart) {
        [shopCart MR_deleteEntity];
        [[NSManagedObjectContext MR_defaultContext] MR_saveToPersistentStoreAndWait];
    }
}

#pragma mark - 轉(zhuǎn)換

// JYShopCart ==> JYShopCartViewModel
- (JYShopCartViewModel *)transformShopCartToShopCartViewModel:(JYShopCart *)shopCart {
    if (!shopCart) {
        return nil;
    }
    JYShopCartViewModel *shopCartViewModel = [[JYShopCartViewModel alloc] init];
    shopCartViewModel.shopModel  = shopCart.shopModel;
    shopCartViewModel.goodsArray = [self unArchivedGoodsArrayWithData:shopCart.goodsArrayData];
    shopCartViewModel.createTime = shopCart.createTime;
    shopCartViewModel.updateTime = shopCart.updateTime;
    return shopCartViewModel;
}

// shopCart集合 ==> shopCartViewModel集合
- (NSArray *)transformShopCartsToShopCartViewModels:(NSArray *)shopCarts {
    if (shopCarts.count <= 0) {
        return nil;
    }
    
    NSMutableArray *shopCartViewModels = [NSMutableArray array];
    for (JYShopCart *shopCart in shopCarts) {
        JYShopCartViewModel *model = [self transformShopCartToShopCartViewModel:shopCart];
        [shopCartViewModels addObject:model];
    }
    return shopCartViewModels;
}

#pragma mark - 獲取用戶標(biāo)識(shí)

- (NSString *)userIDByLogin {
    if ([OPTRuntime sharedInstance].currentNewUser.logined && [OPTRuntime sharedInstance].currentNewUser.uid.length > 0) {
        return [OPTRuntime sharedInstance].currentNewUser.uid;
    }
    return kUnLoginUserID;
}

#pragma mark - 商品的歸檔和解檔

- (NSData *)archivedDataWithGoodsArray:(NSArray *)goodsArray {
    if (goodsArray.count > 0) {
        NSMutableArray *carts = [NSMutableArray array];
        for (JYGoodsCartViewModel *model  in goodsArray) {
            JYGoodsCart *goodsCart = [[JYGoodsCart alloc] init];
            goodsCart.goodsID   = model.goodsModel.goodsId;
            goodsCart.goodsData = [self archivedDataWithGoodsModel:model.goodsModel];
            goodsCart.quantity  = model.quantity;
            [carts addObject:goodsCart];
        }
        return [NSKeyedArchiver archivedDataWithRootObject:carts];
    }
    return nil;
}

- (NSArray *)unArchivedGoodsArrayWithData:(NSData *)goodsArrayData {
    if (goodsArrayData) {
        NSArray *carts = [NSKeyedUnarchiver unarchiveObjectWithData:goodsArrayData];
        NSMutableArray *goodsViewModels = [NSMutableArray array];
        for (JYGoodsCart *cart in carts) {
            JYGoodsCartViewModel *model = [[JYGoodsCartViewModel alloc] init];
            model.goodsModel = [self unArchivedWithData:cart.goodsData];
            model.quantity   = cart.quantity;
            [goodsViewModels addObject:model];
        }
        return goodsViewModels;
    }
    return nil;
}

- (NSData *)archivedDataWithGoodsModel:(NewGoodsModel *)goodsModel {
    if (goodsModel) {
        return [NSKeyedArchiver archivedDataWithRootObject:goodsModel];
    }
    return nil;
}

- (NewGoodsModel *)unArchivedWithData:(NSData *)goodsData {
    if (goodsData) {
        return [NSKeyedUnarchiver unarchiveObjectWithData:goodsData];
    }
    return nil;
}

#pragma mark - 發(fā)送更新購(gòu)物車的通知

- (void)postNotificationAfterShopCartIsChange {
    [[NSNotificationCenter defaultCenter] postNotificationName:kObserverShopCartDidChange object:nil];
}

@end

結(jié)尾:

以上是個(gè)人對(duì)購(gòu)物車的簡(jiǎn)單理解,局限于水平的問題,可能還存在一些問題,如有疑問或建議,歡迎積極留言探討。>v<

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 本文是對(duì) MagicalRecord github上的翻譯 正文:注意: MagicalRecord 在 ARC...
    騂躍神話閱讀 2,136評(píng)論 1 5
  • Android 自定義View的各種姿勢(shì)1 Activity的顯示之ViewRootImpl詳解 Activity...
    passiontim閱讀 179,063評(píng)論 25 709
  • 發(fā)現(xiàn) 關(guān)注 消息 iOS 第三方庫(kù)、插件、知名博客總結(jié) 作者大灰狼的小綿羊哥哥關(guān)注 2017.06.26 09:4...
    肇東周閱讀 15,381評(píng)論 4 61
  • 去國(guó)外參展,而且是很多人羨慕的米國(guó)。感覺遙望不可及,前期的準(zhǔn)備資料都是由展覽公司待辦的,省去了不少麻煩,網(wǎng)上預(yù)約,...
    萍萍_7444閱讀 498評(píng)論 4 0
  • 水榭歌臺(tái)的戲子笑, 是有閉月的容,還是羞花的貌。 該是瓊漿玉液做的箏與簫, 否則又怎會(huì)把人迷的神魂顛倒。 臘月寒冬...
    紅薯君閱讀 298評(píng)論 0 1

友情鏈接更多精彩內(nèi)容