Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit fb8aa7a

Browse files
终结使用MVVM With RAC的Demo
1 parent 2b90e7a commit fb8aa7a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

51 files changed

+1819
-194
lines changed

‎MHDevelopExample/MHDevelopExample.xcodeproj/project.pbxproj‎

Lines changed: 90 additions & 2 deletions
Large diffs are not rendered by default.

‎MHDevelopExample/MHDevelopExample/AppDelegate.m‎

Lines changed: 30 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,14 @@
1111
#import "MHExampleController.h"
1212

1313

14+
#if defined(DEBUG)||defined(_DEBUG)
15+
#import "JPFPSStatus.h"
16+
#import <FBMemoryProfiler/FBMemoryProfiler.h>
17+
#import <FBRetainCycleDetector/FBRetainCycleDetector.h>
18+
#import "CacheCleanerPlugin.h"
19+
#import "RetainCycleLoggerPlugin.h"
20+
#endif
21+
1422

1523
@interface AppDelegate ()
1624
/**
@@ -23,7 +31,11 @@ @interface AppDelegate ()
2331
@end
2432

2533
@implementation AppDelegate
26-
34+
{
35+
#if defined(DEBUG)||defined(_DEBUG)
36+
FBMemoryProfiler *memoryProfiler;
37+
#endif
38+
}
2739

2840
#pragma mark- 获取appdelegate
2941
+ (AppDelegate *)sharedDelegate
@@ -51,38 +63,29 @@ - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(
5163
[self.window makeKeyAndVisible];
5264

5365
#if defined(DEBUG)||defined(_DEBUG)
54-
[[JPFPSStatus sharedInstance] open];
66+
[self_configDebugModelTools];
5567
#endif
5668

57-
5869
return YES;
5970
}
6071

6172

62-
- (void)applicationWillResignActive:(UIApplication *)application {
63-
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
64-
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
65-
}
66-
67-
68-
- (void)applicationDidEnterBackground:(UIApplication *)application {
69-
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
70-
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
71-
}
72-
73-
74-
- (void)applicationWillEnterForeground:(UIApplication *)application {
75-
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
76-
}
77-
78-
79-
- (void)applicationDidBecomeActive:(UIApplication *)application {
80-
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
81-
}
82-
83-
84-
- (void)applicationWillTerminate:(UIApplication *)application {
85-
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
73+
#pragma mark - 调试(DEBUG)模式
74+
- (void)_configDebugModelTools
75+
{
76+
/// 显示FPS
77+
[[JPFPSStatus sharedInstance] open];
78+
79+
/// 内存分析+通过Runtime监测循环引用+跟踪oc对象的分配情况
80+
NSArray *filters = @[FBFilterBlockWithObjectIvarRelation([UIView class], @"_subviewCache"),
81+
FBFilterBlockWithObjectIvarRelation([UIPanGestureRecognizer class], @"_internalActiveTouches")];
82+
FBObjectGraphConfiguration *configuration =
83+
[[FBObjectGraphConfiguration alloc] initWithFilterBlocks:filters
84+
shouldInspectTimers:NO];
85+
memoryProfiler = [[FBMemoryProfiler alloc] initWithPlugins:@[[CacheCleanerPlugin new],
86+
[RetainCycleLoggerPlugin new]]
87+
retainCycleDetectorConfiguration:configuration];
88+
[memoryProfiler enable];
8689
}
8790

8891

‎MHDevelopExample/MHDevelopExample/Classes/Comment/TwoTableView/MHTopicTwoController.m‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,7 +158,7 @@ - (void)_setupData
158158
{
159159
NSDate *date = [NSDate date];
160160
// 初始化100条数据
161-
for (NSInteger i = 30; i>0; i--) {
161+
for (NSInteger i = 1; i>0; i--) {
162162

163163
// 话题
164164
MHTopic *topic = [[MHTopic alloc] init];
@@ -176,7 +176,7 @@ - (void)_setupData
176176
topic.text = [self.textString substringFromIndex:[NSObject mh_randomNumber:0 to:self.textString.length-1]];
177177
topic.user = self.users[[NSObject mh_randomNumber:0 to:9]];
178178

179-
NSInteger commentsCount = [NSObject mh_randomNumber:0 to:15];
179+
NSInteger commentsCount = 100;//[NSObject mh_randomNumber:0 to:15];
180180
topic.commentsCount = commentsCount;
181181
for (NSInteger j = 0; j<commentsCount; j++) {
182182
MHComment *comment = [[MHComment alloc] init];

‎MHDevelopExample/MHDevelopExample/Classes/Comment/TwoTableView/View/MHTopicCell.m‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,7 @@ + (instancetype)cellWithTableView:(UITableView *)tableView
6262
if (!cell) {
6363
cell = [[self alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
6464
cell.selectionStyle = UITableViewCellSelectionStyleNone;
65+
6566
}
6667
return cell;
6768
}

‎MHDevelopExample/MHDevelopExample/Classes/Comment/TwoTableView/View/MHTopicCommentCell.m‎

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ + (instancetype)cellWithTableView:(UITableView *)tableView
3131
MHTopicCommentCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
3232
if (!cell) {
3333
cell = [[self alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:ID];
34-
3534
}
3635
return cell;
3736
}

‎MHDevelopExample/MHDevelopExample/Classes/MVC&MVVM/Base/BaseView/SUGoodsCell.h‎

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -41,6 +41,10 @@ typedef void(^SUGoodsCellReplyClickedHandler)(SUGoodsCell *goodsCell);
4141
*/
4242
typedef void(^SUGoodsCellThumbClickedHandler)(SUGoodsCell *goodsCell);
4343

44+
/**
45+
* 商品图片view被点击
46+
*/
47+
typedef void(^SUGoodsCellPictureViewClickedHandler)(SUGoodsCell *goodsCell);
4448
//// 以上 MVC 和 MVVM without RAC 的事件回调的使用的场景,如果使用MVVM With RAC的请自行ignore
4549

4650

@@ -66,6 +70,8 @@ typedef void(^SUGoodsCellThumbClickedHandler)(SUGoodsCell *goodsCell);
6670
@property (nonatomic, readwrite, copy) SUGoodsCellReplyClickedHandler replyClickedHandler;
6771
/// 点赞按钮被点击
6872
@property (nonatomic, readwrite, copy) SUGoodsCellThumbClickedHandler thumbClickedHandler;
73+
/// 商品照片view被点击
74+
@property (nonatomic, readwrite, copy) SUGoodsCellPictureViewClickedHandler pictureViewClickedHandler;
6975
//// 以上 MVC 和 MVVM without RAC 的事件回调的使用的场景,如果使用MVVM With RAC的请自行ignore
7076

7177
@end

‎MHDevelopExample/MHDevelopExample/Classes/MVC&MVVM/Base/BaseView/SUGoodsCell.m‎

Lines changed: 104 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -54,16 +54,23 @@ @interface SUGoodsCell()<
5454
@property (weak, nonatomic) IBOutlet UIView *sepLineView;
5555
/// 发布时间
5656
@property (weak, nonatomic) IBOutlet UILabel *publishTimeLabel;
57-
57+
/// 商品图片布局
5858
@property (weak, nonatomic) IBOutlet UICollectionViewFlowLayout *flowLayout;
5959

6060
/// 点赞按钮
6161
@property (weak, nonatomic) IBOutlet UIButton *thumbBtn;
6262

63-
//// 以下 MVVM使用的场景,如果使用MVC的请自行ignore
63+
/// 以下 MVVM使用的场景,如果使用MVC的请自行ignore
6464
/// viewModle
6565
@property (nonatomic, readwrite, strong) SUGoodsItemViewModel *viewModel;
6666
//// 以上 MVVM使用的场景,如果使用MVC的请自行ignore
67+
68+
/// 以下 MVVM With RAC使用的场景,如果使用其他的的请自行ignore
69+
70+
/// 显示HUD
71+
@property (nonatomic, readwrite, assign) BOOL showHUD;
72+
73+
/// 以上 MVVM With RAC使用的场景,如果使用其他的的请自行ignore
6774
@end
6875

6976
@implementation SUGoodsCell
@@ -95,7 +102,7 @@ - (void)awakeFromNib{
95102
self.extraFee.backgroundColor = SUGlobalPinkColor;
96103
self.extraFee.textColor = [UIColor whiteColor];
97104
self.extraFee.layer.cornerRadius = 2;
98-
#warning FIXME:需要优化,避免离屏渲染
105+
#warning COderMikeHe FIXME:需要优化,避免离屏渲染
99106
self.extraFee.layer.masksToBounds = YES;
100107

101108
/// UICollectionView注册cell
@@ -114,9 +121,32 @@ - (void)awakeFromNib{
114121
//// 使用MVC 和 MVVM without RAC 的事件回调
115122
[self _addActionDealForMVCOrMVVMWithoutRAC];
116123

124+
125+
117126
//// MVVM with RAC 的事件回调
118127
[self _addActionDealForMVVMWithRAC];
119128

129+
130+
//// 以下 MVVM With RAC 模式的的数据绑定 如果使用其他的模式的请自行ignore
131+
@weakify(self);
132+
133+
/// 按钮选中状态
134+
[RACObserve(self, viewModel.goods.isLike).deliverOnMainThread.distinctUntilChanged subscribeNext:^(NSNumber *isLike) {
135+
@strongify(self);
136+
if (!self.showHUD) return ;
137+
self.thumbBtn.selected = isLike.boolValue;
138+
NSString *tips = (isLike.boolValue)?@"收藏商品成功":@"取消收藏商品";
139+
[MBProgressHUD mh_showTips:tips];
140+
141+
}];
142+
/// 监听点赞数据
143+
[RACObserve(self, viewModel.goods.likes).deliverOnMainThread.distinctUntilChanged
144+
subscribeNext:^(NSString * likes) {
145+
@strongify(self);
146+
[self.thumbBtn setTitle:likes forState:UIControlStateNormal];
147+
148+
}];
149+
//// 以下 MVVM With RAC 的事件回调的使用的场景,如果使用其他的模式的请自行ignore
120150
}
121151

122152
// 以下 MVVM使用的场景,如果使用MVC的请自行ignore
@@ -125,6 +155,9 @@ - (void)bindViewModel:(SUGoodsItemViewModel *)viewModel
125155
{
126156
self.viewModel = viewModel;
127157

158+
self.showHUD = NO;
159+
160+
128161
/// 头像
129162
[MHWebImageTool setImageWithURL:viewModel.goods.avatar placeholderImage:placeholderUserIcon() imageView:self.userHeadImageView];
130163

@@ -224,7 +257,7 @@ - (void)setGoodsFrame:(SUGoodsFrame *)goodsFrame{
224257
/// 点赞数
225258
[self.thumbBtn setTitle:goods.likes forState:UIControlStateNormal];
226259
self.thumbBtn.selected = goods.isLike;
227-
260+
228261
}
229262
//// 以上 MVC使用的场景,如果使用MVVM的请自行ignore
230263

@@ -261,6 +294,12 @@ - (void)_addActionDealForMVCOrMVVMWithoutRAC
261294
@strongify(self);
262295
!self.thumbClickedHandler?:self.thumbClickedHandler(self);
263296
} forControlEvents:UIControlEventTouchUpInside];
297+
298+
/// 图片被点击
299+
[self.optimalProductCollectionView addGestureRecognizer:[[UITapGestureRecognizer alloc] bk_initWithHandler:^(UIGestureRecognizer *sender, UIGestureRecognizerState state, CGPoint location) {
300+
@strongify(self);
301+
!self.pictureViewClickedHandler?:self.pictureViewClickedHandler(self);
302+
}]];
264303
}
265304
//// 以上 MVC 和 MVVM without RAC 的事件回调的使用的场景,如果使用MVVM With RAC的请自行ignore
266305

@@ -272,31 +311,67 @@ - (void)_addActionDealForMVCOrMVVMWithoutRAC
272311
/// 事件处理 我这里使用 block 来回调事件 (PS:大家可以自行决定)
273312
- (void)_addActionDealForMVVMWithRAC
274313
{
275-
///
276-
// @weakify(self);
277-
// [[self.GPSBtn rac_signalForControlEvents:UIControlEventTouchUpInside]
278-
// subscribeNext:^(UIButton *sender) {
279-
// @strongify(self);
280-
// ///
281-
// NSLog(@"---位置被点击---");
282-
// [self.viewModel.locationDidClickedSuject sendNext:self.viewModel];
283-
// }];
284-
//
285-
// self.userHeadImageView.userInteractionEnabled = YES;
286-
// UITapGestureRecognizer *avatarTapGr = [[UITapGestureRecognizer alloc] init];
287-
// [self.userHeadImageView addGestureRecognizer:avatarTapGr];
288-
// [avatarTapGr.rac_gestureSignal subscribeNext:^(id x) {
289-
// NSLog(@"---头像被点击---");
290-
// [self.viewModel.avatarDidClickedSuject sendNext:self.viewModel];
291-
// }];
292-
//
293-
// UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] init];
294-
// [self.optimalProductCollectionView addGestureRecognizer:singleTap];
295-
// [singleTap.rac_gestureSignal subscribeNext:^(id x) {
296-
// @strongify(self);
297-
// NSLog(@"---UICollectionView---");
298-
// [self.viewModel.pictureDidClickedSuject sendNext:self.viewModel];
299-
// }];
314+
@weakify(self);
315+
/// 头像
316+
/// Fixed : 这个方法会导致上面的使用 MVC 或者 MVVM without RAC 情况的头像点击失效 但是理论上是绝对不会出现这两种模式共存的情况的 这里笔者只是为了做区分而已
317+
UITapGestureRecognizer *avatarTapGr = [[UITapGestureRecognizer alloc] init];
318+
[self.userHeadImageView addGestureRecognizer:avatarTapGr];
319+
[[avatarTapGr.rac_gestureSignal
320+
takeUntil:self.rac_prepareForReuseSignal]
321+
subscribeNext:^(id x) {
322+
@strongify(self);
323+
[self.viewModel.didClickedAvatarSubject sendNext:self.viewModel];
324+
/// MVC 或者 MVVM without RAC 有效
325+
!self.avatarClickedHandler?:self.avatarClickedHandler(self);
326+
}];
327+
328+
/// 地址
329+
[[[self.GPSBtn rac_signalForControlEvents:UIControlEventTouchUpInside]
330+
takeUntil:self.rac_prepareForReuseSignal]
331+
subscribeNext:^(UIButton *sender) {
332+
@strongify(self);
333+
[self.viewModel.didClickedLocationSubject sendNext:self.viewModel];
334+
}];
335+
336+
/// 回复
337+
[[[self.replyBtn rac_signalForControlEvents:UIControlEventTouchUpInside]
338+
takeUntil:self.rac_prepareForReuseSignal]
339+
subscribeNext:^(UIButton *sender) {
340+
@strongify(self);
341+
[self.viewModel.didClickedReplySubject sendNext:self.viewModel];
342+
}];
343+
344+
CALayer
345+
/// 收藏按钮
346+
[[[self.thumbBtn rac_signalForControlEvents:UIControlEventTouchUpInside]
347+
takeUntil:self.rac_prepareForReuseSignal]
348+
subscribeNext:^(UIButton *sender) {
349+
@strongify(self);
350+
/// 执行
351+
self.thumbBtn.enabled = NO;
352+
self.showHUD = YES;
353+
[MBProgressHUD mh_showProgressHUD:@"Loading..."];
354+
@weakify(self)
355+
[[[self.viewModel.operationCommand
356+
execute:self.viewModel]
357+
deliverOnMainThread]
358+
subscribeCompleted:^{
359+
@strongify(self)
360+
self.thumbBtn.enabled = YES;
361+
self.showHUD = NO;
362+
}];
363+
364+
}];
365+
366+
UITapGestureRecognizer *singleTap = [[UITapGestureRecognizer alloc] init];
367+
[self.optimalProductCollectionView addGestureRecognizer:singleTap];
368+
[[singleTap.rac_gestureSignal
369+
takeUntil:self.rac_prepareForReuseSignal]
370+
subscribeNext:^(id x) {
371+
@strongify(self);
372+
/// MVC 或者 MVVM without RAC 有效
373+
!self.pictureViewClickedHandler?:self.pictureViewClickedHandler(self);
374+
}];
300375

301376
}
302377
//// 以上 MVVM With RAC 的事件回调的使用的场景,如果使用其他的模式的请自行ignore
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// SUPublicViewModel2.h
3+
// MHDevelopExample
4+
//
5+
// Created by senba on 2017年6月19日.
6+
// Copyright © 2017年 CoderMikeHe. All rights reserved.
7+
//
8+
9+
#import "SUViewModel2.h"
10+
11+
@interface SUPublicViewModel2 : SUViewModel2
12+
13+
@end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// SUPublicViewModel2.m
3+
// MHDevelopExample
4+
//
5+
// Created by senba on 2017年6月19日.
6+
// Copyright © 2017年 CoderMikeHe. All rights reserved.
7+
//
8+
9+
#import "SUPublicViewModel2.h"
10+
11+
@implementation SUPublicViewModel2
12+
13+
@end
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
//
2+
// SUPublicWebController2.h
3+
// MHDevelopExample
4+
//
5+
// Created by senba on 2017年6月19日.
6+
// Copyright © 2017年 CoderMikeHe. All rights reserved.
7+
// MVVM With RAC的 跳转到WebView的统一加载控制器 -- C
8+
9+
#import "SUWebViewController2.h"
10+
#import "SUPublicWebViewModel2.h"
11+
@interface SUPublicWebController2 : SUWebViewController2
12+
13+
@end

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /