码迷,mamicode.com
首页 > 移动开发 > 详细

MAKA - iOS版本分析与模仿实现

时间:2015-09-01 13:49:25      阅读:408      评论:0      收藏:0      [点我收藏+]

标签:

Maka上周三发布了iOS客户端1.0。于是做了竞品分析与模仿实现。

 

1. 功能结构分解

工具:iPhone,MindNode。

以下是主要的功能结构分解。从功能与模块来看,实现比较完整,工作量分布也比较平衡。非重要模块都采用最简单的实现方式。

技术分享

 

 

2. API分析

工具:Charles Proxy

以下是主要的API。

模块

名称

URL

Method

说明

用户

注册

/app/user/register

POST

http://api.maka.im

登陆

/app/user/login

POST

 

忘记密码

/app/user/forgetpassword

POST

 

用户信息

/app/user/{$user_id}

GET

 

修改用户信息

/app/user/{$user_id}

PUT

 

事件

我的事件列表

/app/events

GET

 

创建

/app/event

POST

 

更新

/app/event/{$event_id}

PUT

 

发布

/app/event/{$event_id}

POST

 

创作

主分类

/app/specialCategories

GET

 

模板分类

/app/templates

GET

 

模板页

/app/template/{$template_id}

GET

 

图集分类

/app/pictureIndex

GET

 

图片列表

/app/pictures

GET

 

热门

公开事件

/app/publicEvents

GET

 

分类

/app/tagCategories

GET

 

 

3. 架构分析

通过数据分析,与客户端通信的主要服务器有

技术分享

 

 

 

4. 模仿实现

4.1 iOS架构

按照功能模块划分。

技术分享

4.2 工程结构

二层设计 + 按模块划分 + MVVM

 

技术分享

 

4.3 API层设计

使用网络库:AFNetworking-RACExtensions。

使用单件模式 + OC扩展的方式实现接口的模块划分。采用响应式编程方式。显式参数+信号返回。

技术分享

 

 用户模块接口定义

 1 @interface MKAPIClient (User)
 2 
 3 /**
 4  *  用户注册
 5  *
 6  *  @param email    邮箱
 7  *  @param password 密码
 8  *
 9  *  @return 信号
10  */
11 - (RACSignal *)registWithEmail:(NSString *)email password:(NSString *)password;
12 
13 
14 /**
15  *  用户登陆
16  *
17  *  @param email    邮箱
18  *  @param password 密码
19  *
20  *  @return 信号
21  */
22 - (RACSignal *)loginWithEmail:(NSString *)email password:(NSString *)password;
23 
24 
25 /**
26  *  忘记密码
27  *
28  *  @param email 邮箱
29  *
30  *  @return 信号
31  */
32 - (RACSignal *)forgetPasswordWithEmail:(NSString *)email;
33 
34 
35 /**
36  *  用户信息
37  *
38  *  @return 信号
39  */
40 - (RACSignal *)userInfo;
41 
42 /**
43  *  修改用户信息
44  *
45  *  @param key   字段
46  *  @param value 值
47  *
48  *  @return 信号
49  */
50 - (RACSignal *)updateUserInfoWithKey:(NSString *)key value:(NSString *)value;
51 
52 @end

 

 

eg. 登陆接口实现

 1 /**
 2  *  用户登陆
 3  *
 4  *  @param email    邮箱
 5  *  @param password 密码
 6  *
 7  *  @return 信号
 8  */
 9 - (RACSignal *)loginWithEmail:(NSString *)email password:(NSString *)password {
10     NSParameterAssert(email);
11     NSParameterAssert(password);
12     
13     NSDictionary *params = @{@"email" : email, @"password" : password};
14     
15     @weakify(self);
16     return [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
17         @strongify(self);
18         return [[self.client rac_POST:@"/app/user/login" parameters:params] subscribeNext:^(RACTuple *x) {
19             NSDictionary *result = x.first;
20             
21             @try {
22                 if ([result[@"code"] intValue] == 200) {
23                     NSDictionary *data = result[@"data"];
24                     self.uid = [data[@"uid"] intValue];
25                     self.token = data[@"token"];
26                     
27                     [subscriber sendNext:data];
28                 } else {
29                     NSError *err = [NSError errorWithDomain:MKAPIClientErrorDomain code:[result[@"code"] intValue] userInfo:nil];
30                     [subscriber sendError:err];
31                 }
32             } @catch (NSException *exception) {
33                 NSError *err = [NSError errorWithDomain:MKAPIClientErrorDomain code:10001 userInfo:nil];
34                 [subscriber sendError:err];
35             }
36         } error:^(NSError *error) {
37             [subscriber sendError:error];
38         } completed:^{
39             [subscriber sendCompleted];
40         }];
41     }] setNameWithFormat:@"%s", __FUNCTION__];
42 }

 

4.3 业务逻辑层

这层还没想好怎么做比较好。暂时使用MVVM的VM来替代业务逻辑层。

 

4.4 UI层实现

主要采用MVVM模式,简单界面还是使用MVC实现。

说明:

1. 下图中的MKPublicEventItem为MKPublicEventCell的属性,不是Domain。参考:UINavigationItem设计。

技术分享

 

2. Domain与Item关系。Item为PL层数据。

说明:MKItem为所有表现层数据的基类,提供与Domain映射的基本功能。 参考Three20的Item设计和UIView tag值设计。

 

1 @interface MKItem : NSObject
2 
3 @property(nonatomic, weak)NSObject *weakRef;
4 @property(nonatomic, strong)NSObject *ref;
5 @property(nonatomic, strong)NSIndexPath *indexPath;
6 @property(nonatomic, assign)int tag;
7 
8 @end

 

XXXItem只提供UI显示的数据。属于贫血模型。

1 @interface MKPublicEventItem : MKItem
2 
3 @property(nonatomic, copy)NSString *title;
4 @property(nonatomic, copy)NSString *cover;
5 @property(nonatomic, copy)NSString *username;
6 @property(nonatomic, copy)NSString *publishTime;
7 
8 @end

 

MKPublicEventItem+Event。该扩展用于从Domain创建Item方法。功能与reformer相同。参考: iOS应用架构谈 网络层设计方案

 

 1 @implementation MKPublicEventItem (Event)
 2 
 3 
 4 + (instancetype)itemWithDictionary:(NSDictionary *)event {
 5     MKPublicEventItem *item = [[MKPublicEventItem alloc] init];
 6     item.title = event[@"title"];
 7     item.cover = event[@"firstImgUrl"];
 8     item.username = event[@"author"];
 9     item.publishTime = event[@"publishTime"];
10     item.ref = event;
11     
12     return item;
13 }
14 
15 - (NSString *)eventId {
16     return [(NSDictionary *)self.ref objectForKey:@"id"];
17 }
18 
19 @end

 

MKPublicEventCell

说明:

1. 属性使用lazy load方式创建。

 

 1 @interface MKPublicEventCell : UICollectionViewCell
 2 
 3 
 4 @property(nonatomic, strong)MKPublicEventItem *item;
 5 
 6 + (float)cellHeightWithWidth:(float)width;
 7 
 8 @end
 9 
10 
11 @interface MKPublicEventCell ()
12 
13 @property(nonatomic, strong)UIImageView *imageView;
14 @property(nonatomic, strong)MKPublicEventToolbar *toolbar;
15 
16 @end
17 
18 @implementation MKPublicEventCell
19 
20 + (float)cellHeightWithWidth:(float)width {
21     return width * 504/320 + [MKPublicEventToolbar toolbarHeight];
22 }
23 
24 - (instancetype)initWithFrame:(CGRect)frame {
25     if (self = [super initWithFrame:frame]) {
26         [self setup];
27     }
28     
29     return self;
30 }
31 
32 - (UIImageView *)imageView {
33     if (!_imageView) {
34         UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectZero];
35         imageView.backgroundColor = [UIColor randomLightColor];
36         imageView.contentMode = UIViewContentModeScaleAspectFill;
37         imageView.clipsToBounds = YES;
38         _imageView = imageView;
39     }
40     
41     return _imageView;
42 }
43 
44 - (MKPublicEventToolbar *)toolbar {
45     if (!_toolbar) {
46         MKPublicEventToolbar *toolbar = [[MKPublicEventToolbar alloc] initWithFrame:CGRectZero];
47         _toolbar = toolbar;
48     }
49     
50     return _toolbar;
51 }
52 
53 - (void)setup {
54     [self.contentView addSubview:self.imageView];
55     [self.contentView addSubview:self.toolbar];
56 }
57 
58 - (void)layoutSubviews {
59     [super layoutSubviews];
60     // h‘/w‘ = h/w
61     self.imageView.frame = CGRectMake(0, 0, self.bounds.size.width, [MKPublicEventCell cellHeightWithWidth:self.bounds.size.width] - [MKPublicEventToolbar toolbarHeight]);
62     self.toolbar.frame = CGRectMake(0, self.imageView.bounds.size.height, self.bounds.size.width, [MKPublicEventToolbar toolbarHeight]);
63 }
64 
65 - (void)setItem:(MKPublicEventItem *)item {
66     _item = item;
67     
68     [self.imageView sd_setImageWithURL:[NSURL URLWithString:item.cover] placeholderImage:nil];
69     self.toolbar.usernameLabel.text = item.username;
70     self.toolbar.titleLabel.text = item.title;
71     self.toolbar.dateLabel.text = item.publishTime;
72 }
73 
74 @end

 

5. 单元测试

使用Specta + Expecta+ReactiveCocoa

 

 1 SpecBegin(User)
 2 
 3 describe(@"用户", ^{
 4     
 5     __block MKAPIClient *client;
 6     beforeAll(^{
 7         client = [MKAPIClient defaultClient];
 8     });
 9     
10     beforeEach(^{
11         
12     });
13     
14     context(@"当登陆", ^{
15         it(@"应该成功", ^{
16             RACSignal *signal = [client loginWithEmail:@"test@test.com" password:@"password"];
17             expect(signal).will.complete();
18         });
19     });
20     
21     afterEach(^{
22 
23     });
24     
25     afterAll(^{
26 
27     });
28 });
29 
30 SpecEnd

 

 

6. 效果

周末花了2天时间做分析并且实现。

1. API层对接完毕。

2. 基础框架搭建完毕。

3. 实现热门基本UI。

技术分享

 

 

7. 总结

由于时间比较仓促。还没有对创作模块做详细分析。后续在补上。

 

MAKA - iOS版本分析与模仿实现

标签:

原文地址:http://www.cnblogs.com/kim4apple/p/4775374.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!