@implementation ASHTempViewController
#pragma mark - app logic
- (void)sendBroadcastWithSuccessBlock:(void (^)(void))successBlock
{
BOOL haveRead = [[NSUserDefaults standardUserDefaults] boolForKey:@"haveReadBroadcastTip"];
if (haveRead == NO) {
NSString *title = @"1、发布广播,全服玩家都可以看到;\n2、禁止发布反动、政治、色情、辱骂、广告等不良言论,否则将会遭到删除、封号处理。";
__weak typeof(self) wself = self;
[self showAlertWithMsg:title callback:^{
[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:@"haveReadBroadcastTip"];
[wself showSendViewWithSuccessBlock:successBlock];
}];
} else {
[self showSendViewWithSuccessBlock:successBlock];
}
}
- (void)showSendViewWithSuccessBlock:(void(^)(void))successBlock
{
__weak typeof(self) wself = self;
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"发送广播" message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.placeholder = @"说点什么...";
}];
[alertController addAction:[UIAlertAction actionWithTitle:@"发送" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSString *msg = [[alertController textFields][0] text];
[wself sendBroadcast:msg successBlock:successBlock];
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"Canelled");
}]];
[self presentViewController:alertController animated:YES completion:nil];
}
- (void)sendBroadcast:(NSString *)msg successBlock:(void(^)(void))successBlock
{
__weak typeof(self) wself = self;
[self sendBroadcastRequestWithMsg:msg successBlock:^{
//data operation
!successBlock ?: successBlock();
} failureBlock:^(NSError *error) {
[wself showAlertWithMsg:error.localizedDescription callback:nil];
}];
}
#pragma mark - networks
- (void)sendBroadcastRequestWithMsg:(NSString *)msg successBlock:(void(^)(void))successBlock failureBlock:(void(^)(NSError *error))failureBlock
{
//send request
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
!successBlock ?: successBlock();
});
}
#pragma mark - utils
- (void)showAlertWithMsg:(NSString *)msg callback:(void(^)(void))callback
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:msg preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
!callback ?: callback();
}]];
[self presentViewController:alert animated:YES completion:nil];
}
@end
我又出了一个版本,根据大家的意见整理了下
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//macro.h
#ifndef weakify
#if __has_feature(objc_arc)
#define weakify( x ) autoreleasepool{} __weak __typeof__(x) __weak_##x##__ = x;
#else // #if __has_feature(objc_arc)
#define weakify( x ) autoreleasepool{} __block __typeof__(x) __block_##x##__ = x;
#endif // #if __has_feature(objc_arc)
#endif // #ifndef weakify
#ifndef normalize
#if __has_feature(objc_arc)
#define normalize( x ) try{} @finally{} __typeof__(x) x = __weak_##x##__;
#else // #if __has_feature(objc_arc)
#define normalize( x ) try{} @finally{} __typeof__(x) x = __block_##x##__;
#endif // #if __has_feature(objc_arc)
#endif // #ifndef @normalize
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//store/pref/ASHPrefStore.h
@interface ASHPrefStore : NSObject
+ (BOOL)haveReadBroadcastTip;
+ (void)setHaveReadBroadcastTip;
@end
//store/pref/ASHPrefStore.m
@implementation ASHPrefStore
static NSString *const kHaveReadBroadcastTipKey = @"haveReadBroadcastTip";
+ (BOOL)haveReadBroadcastTip
{
return [[NSUserDefaults standardUserDefaults] boolForKey:kHaveReadBroadcastTipKey];
}
+ (void)setHaveReadBroadcastTip
{
[[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:kHaveReadBroadcastTipKey];
}
@end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//network/ASHNetworkAPI.h
@interface ASHNetworkAPI : NSObject
+ (void)sendBroadcastRequestWithMsg:(NSString *)msg successBlock:(void(^)(void))successBlock failureBlock:(void(^)(NSError *error))failureBlock;
@end
//network/ASHNetworkAPI.m
@implementation ASHNetworkAPI
+ (void)sendBroadcastRequestWithMsg:(NSString *)msg successBlock:(void(^)(void))successBlock failureBlock:(void(^)(NSError *error))failureBlock
{
//send request
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
!successBlock ?: successBlock();
});
}
@end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//utils/ui/ASHAlertUtils.h
@interface ASHAlertUtils : NSObject
+ (void)showAlertWithController:(UIViewController *)controller msg:(NSString *)msg callback:(void(^)(void))callback;
+ (void)showEditAlertWithController:(UIViewController *)controller title:(NSString *)title placeholder:(NSString *)placeholder callback:(void(^)(NSString *content))callback;
@end
//utils/ui/ASHAlertUtils.m
@implementation ASHAlertUtils
#pragma mark - utils
+ (void)showAlertWithController:(UIViewController *)controller msg:(NSString *)msg callback:(void(^)(void))callback
{
UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:msg preferredStyle:UIAlertControllerStyleAlert];
[alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
!callback ?: callback();
}]];
[controller presentViewController:alert animated:YES completion:nil];
}
+ (void)showEditAlertWithController:(UIViewController *)controller title:(NSString *)title placeholder:(NSString *)placeholder callback:(void(^)(NSString *content))callback
{
UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleAlert];
[alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) {
textField.placeholder = placeholder;
}];
[alertController addAction:[UIAlertAction actionWithTitle:@"发送" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {
NSString *content = [[alertController textFields][0] text];
!callback ?: callback(content);
}]];
[alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {
NSLog(@"Canelled");
}]];
[controller presentViewController:alertController animated:YES completion:nil];
}
@end
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
//controller/ASHTempViewController.m
@implementation ASHTempViewController
#pragma mark - app logic
- (void)sendBroadcastWithSuccessBlock:(void (^)(void))successBlock
{
@weakify(self)
void (^showSendBroadcast) (void) = ^{
[ASHAlertUtils showEditAlertWithController:self title:@"发送广播'" placeholder:@"说点什么..." callback:^(NSString *content) {
[ASHNetworkAPI sendBroadcastRequestWithMsg:content successBlock:successBlock failureBlock:^(NSError *error) {
@normalize(self)
!self ?: [ASHAlertUtils showAlertWithController:self msg:error.localizedDescription callback:nil];
}];
}];
};
if ([ASHPrefStore haveReadBroadcastTip]) {
showSendBroadcast();
} else {
NSString *title = @"1、发布广播,全服玩家都可以看到;\n2、禁止发布反动、政治、色情、辱骂、广告等不良言论,否则将会遭到删除、封号处理。";
[ASHAlertUtils showAlertWithController:self msg:title callback:^{
[ASHPrefStore setHaveReadBroadcastTip];
showSendBroadcast();
}];
}
}
@end
1
summer1991 OP 求答疑!
|
2
blacklist 2017-06-15 13:29:39 +08:00
提取出来做个 Helper 类或者函数的合集?
|
3
blacklist 2017-06-15 13:31:58 +08:00
像 NetworkHelper/NetworkUtils,UIHelper/UIUtils,StringHelper/StringUtils 之类独立的代码文件。。。。。。。。。
|
4
winglight2016 2017-06-15 13:37:09 +08:00
加起来也才 100 行代码,等超过 400 行再来优化不迟
|
5
renshaojuncool 2017-06-15 13:41:00 +08:00
可以抽取出来做个工具类或者辅助类,另外,不要为了优化了优化,任何优化都有可能带来新的问题
|
6
summer1991 OP @winglight2016 比如界面上有十个按钮,每个大概都是这个逻辑怎么办?
|
7
guomiaoyou7784 2017-06-15 14:17:25 +08:00
|
8
guomiaoyou7784 2017-06-15 14:21:02 +08:00
VC 做轻,可以考虑将一些常见的 delegate 实现 做"代理实现",网络层逻辑下沉或抽取到 ViewModel 中,再组合到 VC 上。 方法实现可以考虑多用 Category 来减少 同一个.m 文件的代码量(可以查看 Apple 一些 UIKIt 的编码风格,也是有不同的 Category 来划分代码
这么做了之后,直观表现,VC 的职责还是在的,代码并不会集中在一个文件内了 |
9
summer1991 OP @guomiaoyou7784 这个文章我以前看过的,但针对于代码中的上述情况,文章中说的做法没有一个是有效的。能不能将你的想法结合代码具体说明下?
|
10
summer1991 OP @guomiaoyou7784 上边代码中网络请求的代码在网络请求模块,网络调用代码在 vc 中也只有 一行调用 + block 回调,放到 view model 中只是多增加了一层调用,除了更复杂好像没有什么优化。不同按钮的逻辑放在 viewController 的不同分类中,如果在这个逻辑处理中有一些状态需要放到 vc 中,岂不是很麻烦;而且我觉得分类这种形式使用来增强类本身的功能,如果这些逻辑放在这个类的分类中,且用于被这个类自身调用,是不是比较牵强。有具体的例子可以发出来吗?
|
11
summer1991 OP @blacklist 你还木有看清楚我的问题呀亲
|
12
andyL 2017-06-15 14:54:44 +08:00
1.alert 的方法,抽象一些参数出来封装一下
2.数据持久化可以有专门的类来处理,所以也可以封装一下 3.这些确定的字符串用常量来定义比较好 4.这些带 block 的方法已经不用再封装了,但是如果 其他类也要复用的话,可以抽象一下。 |
13
andyL 2017-06-15 14:56:22 +08:00
5.针对 block 上下文 对 self 的弱引用和强引用的变换 可以抽象成宏定义或者静态方法,基本上整个工程都要处处使用到的
|
14
amon 2017-06-15 15:11:27 +08:00
你这个本来就属于逻辑了啊,Controller 里面放逻辑没毛病。
你再优化,也只是把代码挪到别处而已。 比如,你把按钮的事件放到 block 里面,然后把逻辑代码放到 view 里面去,本质上并没有优化,只是让 Controller 代码少了,其它地方代码多了。 感觉把函数分好类就行了。 |
15
summer1991 OP ```Objective-c
//版本 v2 ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //store/pref/ASHPrefStore.h @interface ASHPrefStore : NSObject + (BOOL)haveReadBroadcastTip; + (void)setHaveReadBroadcastTip; @end //store/pref/ASHPrefStore.m @implementation ASHPrefStore static NSString *const kHaveReadBroadcastTipKey = @"haveReadBroadcastTip"; + (BOOL)haveReadBroadcastTip { return [[NSUserDefaults standardUserDefaults] boolForKey:kHaveReadBroadcastTipKey]; } + (void)setHaveReadBroadcastTip { [[NSUserDefaults standardUserDefaults] setObject:@(YES) forKey:kHaveReadBroadcastTipKey]; } @end ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //network/ASHNetworkAPI.h @interface ASHNetworkAPI : NSObject + (void)sendBroadcastRequestWithMsg:(NSString *)msg successBlock:(void(^)(void))successBlock failureBlock:(void(^)(NSError *error))failureBlock; @end //network/ASHNetworkAPI.m @implementation ASHNetworkAPI + (void)sendBroadcastRequestWithMsg:(NSString *)msg successBlock:(void(^)(void))successBlock failureBlock:(void(^)(NSError *error))failureBlock { //send request dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ !successBlock ?: successBlock(); }); } @end ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //utils/ui/ASHAlertUtils.h @interface ASHAlertUtils : NSObject + (void)showAlertWithController:(UIViewController *)controller msg:(NSString *)msg callback:(void(^)(void))callback; + (void)showEditAlertWithController:(UIViewController *)controller title:(NSString *)title placeholder:(NSString *)placeholder callback:(void(^)(NSString *content))callback; @end //utils/ui/ASHAlertUtils.m @implementation ASHAlertUtils #pragma mark - utils + (void)showAlertWithController:(UIViewController *)controller msg:(NSString *)msg callback:(void(^)(void))callback { UIAlertController *alert = [UIAlertController alertControllerWithTitle:nil message:msg preferredStyle:UIAlertControllerStyleAlert]; [alert addAction:[UIAlertAction actionWithTitle:@"确定" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { !callback ?: callback(); }]]; [controller presentViewController:alert animated:YES completion:nil]; } + (void)showEditAlertWithController:(UIViewController *)controller title:(NSString *)title placeholder:(NSString *)placeholder callback:(void(^)(NSString *content))callback { UIAlertController *alertController = [UIAlertController alertControllerWithTitle:title message:nil preferredStyle:UIAlertControllerStyleAlert]; [alertController addTextFieldWithConfigurationHandler:^(UITextField * _Nonnull textField) { textField.placeholder = placeholder; }]; [alertController addAction:[UIAlertAction actionWithTitle:@"发送" style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) { NSString *content = [[alertController textFields][0] text]; !callback ?: callback(content); }]]; [alertController addAction:[UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) { NSLog(@"Canelled"); }]]; [controller presentViewController:alertController animated:YES completion:nil]; } @end ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //macro.h #ifndef weakify #if __has_feature(objc_arc) #define weakify( x ) autoreleasepool{} __weak __typeof__(x) __weak_##x##__ = x; #else // #if __has_feature(objc_arc) #define weakify( x ) autoreleasepool{} __block __typeof__(x) __block_##x##__ = x; #endif // #if __has_feature(objc_arc) #endif // #ifndef weakify #ifndef normalize #if __has_feature(objc_arc) #define normalize( x ) try{} @finally{} __typeof__(x) x = __weak_##x##__; #else // #if __has_feature(objc_arc) #define normalize( x ) try{} @finally{} __typeof__(x) x = __block_##x##__; #endif // #if __has_feature(objc_arc) #endif // #ifndef @normalize ////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// //controller/ASHTempViewController.m @implementation ASHTempViewController #pragma mark - app logic - (void)sendBroadcastWithSuccessBlock:(void (^)(void))successBlock { @weakify(self) void (^showSendBroadcast) (void) = ^{ [ASHAlertUtils showEditAlertWithController:self title:@"发送广播'" placeholder:@"说点什么..." callback:^(NSString *content) { [ASHNetworkAPI sendBroadcastRequestWithMsg:content successBlock:successBlock failureBlock:^(NSError *error) { @normalize(self) !self ?: [ASHAlertUtils showAlertWithController:self msg:error.localizedDescription callback:nil]; }]; }]; }; if ([ASHPrefStore haveReadBroadcastTip]) { showSendBroadcast(); } else { NSString *title = @"1、发布广播,全服玩家都可以看到;\n2、禁止发布反动、政治、色情、辱骂、广告等不良言论,否则将会遭到删除、封号处理。"; [ASHAlertUtils showAlertWithController:self msg:title callback:^{ [ASHPrefStore setHaveReadBroadcastTip]; showSendBroadcast(); }]; } } ``` |
16
summer1991 OP @andyL 可能之前没有描述好,大家都抓着代码细节看 我整理了下代码放在 https://www.v2ex.com/t/368630, 你可以再看看
|
17
zhangchioulin 2017-06-15 23:42:08 +08:00 via iPhone
想简化 vc 代码的话,使用 MVVM 会是一个比较好的途径,另外 MVC 的话可以考虑创建一个 Manager.
|
18
holy_sin 2017-06-16 11:43:48 +08:00
我觉得 rx 可以拯救你
|
19
winglight2016 2017-06-28 21:18:08 +08:00
@summer1991 你提的问题像是不满意这个类,但是说起同个界面 10 个按钮的例子,这又是个方法级的重用,可以理解吧?
|
20
summer1991 OP @winglight2016 可以这么说,需要重用方法,并且这个方法里面能和 VC 一样,能弹窗,能发起网络请求
|
21
summer1991 OP @winglight2016 有好的想法吗亲?
|
22
winglight2016 2017-07-04 12:37:27 +08:00
@summer1991 要求能够弹窗,这个需要完整框架的支持了,不是普通代码能做的,你可以参考一下 MVVM 的框架
|