转自I'm Allen的博客
 
 
原文来自破船的分享
 
原文作者是开发界中知晓度相当高的 Mugunth Kumar,他是 MKNetworkKit 的作者(虽然没有 AFNetworking 使用那么广泛,但也是一个很棒的 Network Kit),更是最近流传甚广的《iOS 5/6 Programming - Pushing The Limits》的作者。
 
文章中 MK 介绍了几点开发中常用的小技巧,几条 Tips 简单易懂,但是很实用,不但可以提高开发效率,而且可以提高代码的可读性和可复用性。
 
Types in Objective-C 和 Naming Conventions 两个章节介绍性内容较多,下面从 Subclassing 开始简单直译一下,第一次翻译,有诸多不到位的地方,各位多包涵。
 
Subclassing 继承/子类
大多语言允许开发者子类化框架所提供的类,但是在 Objective-C 中不完全是这样。大部分常用的类,诸如 NSArray、NSSet、NSDictionary 基本上都是集合类型的。不建议继承这些类,除非你准备转发调用或者实现所有必要的原始方法。
 
在传统的开发语言中,通常会通过继承基础类型(类似 NSArray 的类)来新增方法,重载已有的方法,或是自定义 UI 组件的外观。在 Objective-C 中,一般通过 Category 来扩展新方法。通过混合方法(swizzling the method?)来重载 SDK 提供的实现。以及外观相关的代理协议(Protocol)来定制 UI 组件的外观。
 
虽说如此,还是有一些类是经常会继承它们的,比如 UIViewController、UITableViewController、UIControl 等。继承 UIViewController 大概是开发过程中最棒的一件事,因为它使得添加常见的功能变得异常简单。在我开发的每个 App 中,会有一个继承自 UIViewController 的子类,它实现了一组常用的方法。所有其他的 View Controllers 则都继承自这个基础类。
 
(译者注:Web 开发中也常会有一个用于被继承的 BaseController 来提供公共方法,看来开发是触类旁通的,要多思考)
 
所以,以下继承方法:
  1. @interface MyAppFeaturedYouTubeVideosViewController : UIViewController
应该替换成:
  1. @interface MyAppFeaturedYouTubeVideosFeaturedViewController : MyAppViewController
  2. @interface MyAppViewController : UIViewController
这个公用基础类可以在后续开发过程中用来添加公用的方法。在这个基础父类中,我通常会申明以下方法:
  1. -(UIView*) errorView;
  2. -(UIView*) loadingView;
  3. -(void) showLoadingAnimated:(BOOL) animated;
  4. -(void) hideLoadingViewAnimated:(BOOL) animated;
  5. -(void) showErrorViewAnimated:(BOOL) animated;
  6. -(void) hideErrorViewAnimated:(BOOL) animated;
 
实现如下:
  1. -(UIView*) errorView {
  2. return nil;
  3. }
  4. -(UIView*) loadingView {
  5. return nil;
  6. }
  7. -(void) showLoadingAnimated:(BOOL) animated {
  8. UIView *loadingView = [self loadingView];
  9. loadingView.alpha = 0.0f;
  10. [self.view addSubview:loadingView];
  11. [self.view bringSubviewToFront:loadingView];
  12. double duration = animated ? 0.4f:0.0f;
  13. [UIView animateWithDuration:duration animations:^{
  14. loadingView.alpha = 1.0f;
  15. }];
  16. }
  17. -(void) hideLoadingViewAnimated:(BOOL) animated {
  18. UIView *loadingView = [self loadingView];
  19. double duration = animated ? 0.4f:0.0f;
  20. [UIView animateWithDuration:duration animations:^{
  21. loadingView.alpha = 0.0f;
  22. } completion:^(BOOL finished) {
  23. [loadingView removeFromSuperview];
  24. }];
  25. }
  26. -(void) showErrorViewAnimated:(BOOL) animated {
  27. UIView *errorView = [self errorView];
  28. errorView.alpha = 0.0f;
  29. [self.view addSubview:errorView];
  30. [self.view bringSubviewToFront:errorView];
  31. double duration = animated ? 0.4f:0.0f;
  32. [UIView animateWithDuration:duration animations:^{
  33. errorView.alpha = 1.0f;
  34. }];
  35. }
  36. -(void) hideErrorViewAnimated:(BOOL) animated {
  37. UIView *errorView = [self errorView];
  38. double duration = animated ? 0.4f:0.0f;
  39. [UIView animateWithDuration:duration animations:^{
  40. errorView.alpha = 0.0f;
  41. } completion:^(BOOL finished) {
  42. [errorView removeFromSuperview];
  43. }];
  44. }
 
现在,App 中的每个 View Controller 中,可以很方便的通过调用以上方法来改变当前 View 的状态为 Loading 或者 Error。而且,View Controller 可以通过重载 -errorView 和 -loadingView 方法来提供自定义错误界面和 Loading 界面。
 
你还可以通过重载这个基础类中的 -viewDidLoad 来统一修改所有 View 的表现。比如为所有的 View 添加相同的背景图片或背景色:
 
  1. - (void)viewDidLoad
  2. {
  3. [super viewDidLoad];
  4. self.view.backgroundColor = [UIColor appOffWhiteColor]; // changes all my views to "off-white"
  5. }
 
 
UI Customization 自定义 UI
自定义 UI 可以大致分成两类,一是自定义控件,二是皮肤/主题。前者可以让 App 更出色,而后者是大部分 App 都需要的。我建议给 UIFont 和 UIColor 写 Category 扩展来提供自定义字体和自定义颜色。
 
例如,给 UIFont 添加如下方法:
  1. +(UIFont*) appFontOfSize:(CGFloat) pointSize {
  2. return [UIFont fontWithName:@"MyriadPro-Regular" size:pointSize];
  3. }
  4. +(UIFont*) boldAppFontOfSize:(CGFloat) pointSize {
  5. return [UIFont fontWithName:@"MyriadPro-Black" size:pointSize];
  6. }
你就可以很方便地使用 [UIFont appFontOfSize:13] 得到 MyriadPro-Regular 字体。这样当你的设计需求变更时,就可以很快速的更换整个 App 中的字体。
 
相同的设计模式也可以应用到自定义颜色中。给 UIColor 添加以下方法:
  1. #define GREY(color) [UIColor colorWithRed:color/255.0 green:color/255.0 blue:color/255.0 alpha:1]
  2. +(UIColor*) appBackgroundColor {
  3. return [UIColor colorWithPatternImage:[UIImage imageNamed:@"BGPattern"]];
  4. }
  5. +(UIColor*) appBlack1Color {
  6. return GREY(38);
  7. }
  8. +(UIColor*) appOffWhiteColor {
  9. return GREY(234);
  10. }
 
所以,千万不要用 Interface Builder 来选颜色。
Subclassing UILabels 继承 UILabel
还有一个小窍门,当开发者继承 UILabel、UITextField 和 UITextView 时,通常在 -initWithFrame: 和 -initWithCoder: 方法中设置字体和颜色,参见以下代码:
  1. @implementation AppPrefixLabel
  2. -(void) setup {
  3. self.font = [UIFont fontWithName:@"SourceSansPro-Semibold" size:self.font.pointSize];
  4. self.textColor = [UIColor redColor];
  5. }
  6. -(id) initWithFrame:(CGRect)frame {
  7. if((self = [super initWithFrame:frame])) {
  8. [self setup];
  9. }
  10. return self;
  11. }
  12. -(id) initWithCoder:(NSCoder *)aDecoder {
  13. if((self = [super initWithCoder:aDecoder])) {
  14. [self setup];
  15. }
  16. return self;
  17. }
  18. @end
这个技巧使得开发者可以在 Interface Builder 中自定义这些元素的外观。在 IB 中拖入一个 UILabel,并且修改它的类为你自定义的类,瞬间就完成了这个 Label 字体和颜色的自定义,不用任何多余的代码。
这个技巧多数情况下相当管用,但是当你的 App 支持自定义主题,且用户可以通过设置界面更换主题时,就会显得有些麻烦。
 
-initWithFrame: 和 initWithCoder: 会在 UI 组件创建的时候被调用,所以在这之后如果要改变字体和颜色,就需要很多额外的代码。因此,如果你的 App 支持主题,写一个主题管理器的全局单例来提供全局的主题、字体、颜色。
 
如果你用到了我说的第一个方法,你的 UIFont 的 Category 现在可以这样实现了:
  1. +(UIFont*) appFontOfSize:(CGFloat) pointSize {
  2. NSString *currentFontName = [[ThemeProvider sharedInstance] currentFontName];
  3. return [UIFont fontWithName:currentFontName size:pointSize];
  4. }
UIColor 同理。其实没有正确或错误的方法,上述方法都是可行的。
 
遵从这里提到的设计模式,可以让你的代码干净得像写的很漂亮的 JS/CSS。试着在你的下一个项目中用这些方法吧。
 
Allen 后记
之前在想 iOS 开发到底是否需要一个类似 Web 开发中的所谓的框架,但渐渐发现其实 iOS SDK 本就是一个高度封装了的框架了,可能我们需要的不是更更高层的框架,而是一种好的设计模式、开发习惯和代码结构。因此是不是可以从一个 Project 的层面出发,写一个干净的框架,并且定义一些规范,就是一个很好的“框架”了?而不是非得提供 Router 之类的往 Web 开发框架去靠。

几点iOS开发技巧的更多相关文章

  1. iOS开发技巧系列---详解KVC(我告诉你KVC的一切)

    KVC(Key-value coding)键值编码,单看这个名字可能不太好理解.其实翻译一下就很简单了,就是指iOS的开发中,可以允许开发者通过Key名直接访问对象的属性,或者给对象的属性赋值.而不需 ...

  2. 【转】几点 iOS 开发技巧

    [译] 几点 iOS 开发技巧 原文:iOS Programming Architecture and Design Guidelines 原文来自破船的分享 原文作者是开发界中知晓度相当高的 Mug ...

  3. iOS开发技巧

    一.寻找最近公共View 我们将一个路径中的所有点先放进 NSSet 中.因为 NSSet 的内部实现是一个 hash 表,所以查找元素的时间复杂度变成了 O(1),我们一共有 N 个节点,所以总时间 ...

  4. iOS开发技巧系列---使用链式编程和Block来实现UIAlertView

    UIAlertView是iOS开发过程中最常用的控件之一,是提醒用户做出选择最主要的工具.在iOS8及后来的系统中,苹果更推荐使用UIAlertController来代替UIAlertView.所以本 ...

  5. iOS开发技巧 -- 复用代码片段

    如果你是一位开发人员在开发过程中会发现有些代码无论是在同一个工程中还是在不同工程中使用率会很高,有经验的人会直接封装在一个类里,或者写成一个宏定义或者把这些代码收集起来,下次直接使用,或者放到xcod ...

  6. iOS开发技巧 - Size Class与iOS 8多屏幕适配(一)

    0. 背景: 在iOS开发中,Auto Layout(自动布局)能解决大部分的屏幕适配问题. 但是当iPhone 6和iPhone 6 Plus发布以后, Auto Layout已经不能解决复杂的屏幕 ...

  7. iOS 开发技巧收藏贴 链接整理

    54个技巧 57个技巧 正则表达式

  8. iOS开发技巧-2

    1,打印View所有子视图 po [[self view]recursiveDescription] 2,layoutSubviews调用的调用时机 * 当视图第一次显示的时候会被调用 * 当这个视图 ...

  9. IOS开发技巧快速生成二维码

    随着移动互联网的发展,二维码应用非常普遍,各大商场,饭店,水果店 基本都有二维码的身影,那么ios中怎么生成二维码呢? 下面的的程序演示了快速生成二维码的方法: 在ios里面要生成二维码,需要借助一个 ...

随机推荐

  1. 安装好的IIS,发布成功后打开网站出现错误

      开发web项目时需要安装IIS,在安装好IIS的Windows7本上发布asp.net网站时,web程序已经映射到了本地IIS上,但运行如下错误提示“处理程序“PageHandlerFactory ...

  2. Java线程和多线程(四)——主线程中的异常

    作为Java的开发者,在运行程序的时候会碰到主线程抛异常的情况.如果开发者使用Java的IDE比如Eclipse或者Intellij IDEA的话,可能是不需要直接面对这个问提的,因为IDE会处理运行 ...

  3. CodeForces 567F DP Mausoleum

    本着只贴代码不写分析的题解是在耍流氓的原则,还是决定写点分析. 思路很清晰,参考的官方题解,一下文字仅对题解做一个简要翻译. 题意: 有1~n这n个数,每个数用两次.构成一个长为2n的序列,而且要求序 ...

  4. 02_ThreadLocal语法与源码分析

    文章导读: 早在JDK 1.2的版本中就提供Java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程 ...

  5. CRM知识点汇总(未完💩💩💩💩💩)

    一:项目中每个类的作用 StarkSite 对照admin中的AdminSite,相当于一个容器,用来存放类与类之间的关系. 先实例化对象,然后执行该对象的register方法.将注册类添加到_reg ...

  6. Leetcode 454.四数相加II

    四数相加II 给定四个包含整数的数组列表 A , B , C , D ,计算有多少个元组 (i, j, k, l) ,使得 A[i] + B[j] + C[k] + D[l] = 0. 为了使问题简单 ...

  7. 2017"百度之星"程序设计大赛 - 复赛

    Arithmetic of Bomb  Accepts: 1050  Submissions: 1762  Time Limit: 2000/1000 MS (Java/Others)  Memory ...

  8. 子元素浮动父容器高度不能自适应的CSS解决方法

    百度标题:子元素浮动父容器高度不能自适应的CSS解决方法 从第二份工作开始,已经不怎么写样式了,然后就忘记了一部分,有的也生疏了. 今天碰到子元素意外挤到一起的问题,就问公司前端工程师是怎么回事,F1 ...

  9. 【Vjudge】P1989Subpalindromes(线段树)

    题目链接 水题一道,用线段树维护哈希值,脑补一下加减乱搞搞……注意细节就过了 一定注意细节…… #include<cstdio> #include<cstdlib> #incl ...

  10. HDU——1005Number Sequence(模版题 二维矩阵快速幂+操作符重载)

    Number Sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)T ...