最近在项目开发过程中,在UI开发方面我的一个目标是可以通过XCode自带的Interface Builder进行界面开发,从而实现界面和逻辑的更好分离以及随之而来的更好的维护性和扩展性。不过在交流这想法的过程中,一些同事也提出了很好的建议和顾虑。其中一个我没有意识到的问题就是开发过程中或有很多UIViewController的界面几乎一致,这样如果按常规每个Controller使用一个相应的NIB不仅有些浪费,而且很难保证各个NIB所代表的View之间风格和布局的严格一致。通过交流我们发现可以通过对UIView的扩展,实现从NIB文件中自动加载View,之后通过代码将生成的View绑定到相应的Controller,从而实现NIB的复用。其中,UIView的NIB扩展代码如下:
- // UIView+NIB.h
- @interface UIView (NIB)
- + (id)loadFromNIB;
- @end
- // UIView+NIB.m
- #import "UIView+NIB.h"
- @implementation UIView (NIB)
- + (NSString*)nibName {
- return [self description];
- }
- + (id)loadFromNIB {
- Class klass = [self class];
- NSString *nibName = [self nibName];
- NSArray* objects = [[NSBundle mainBundle] loadNibNamed:nibName owner:self options:nil];
- for (id object in objects) {
- if ([object isKindOfClass:klass]) {
- return object;
- }
- }
- [NSException raise:@"WrongNibFormat" format:@"Nib for '%@' must contain one UIView, and its class must be '%@'", nibName, NSStringFromClass(klass)];
- return nil;
- }
- @end
实现之后总感觉有点欠缺,因为需要通过代码将生成的View绑定到相应的Controller。经过进一步的调查后发现UIViewController可以通过initWithNibName:bundle:实例化,这样就可以为多个Controller指定一个相同的NIB文件了,View的绑定也就不用操心了。在游戏中心中,需要共用NIB文件的Controller就如下自定义的初始化函数进行加载:
- - (id)initWithOptions:(NSDictionary *)options
- {
- if (self = [super initWithNibName:@"MessageController" bundle:nil])
- {
- // Other initializtion code here
- }
- return self;
- }
其中,options可以传入初始化需要的参数。
在项目中,有几个界面的显示和布局差几乎一致,不同的是逻辑和后台数据。这样就可以通过如下调用进行初始化:
- friendNews = [[FriendNewsController alloc] initWithOptions:options];
- friendMessage = [[FriendMessageController alloc] initWithOptions:options];
- sysMessage = [[SystemMessageController alloc] initWithOptions:options];
这样三个不同的Controller都利用MessageController.xib初始化成各自的View,从而实现了NIB文件的复用。
转载于:https://blog.51cto.com/bj007/490233