配色: 字号:
iOS开发中常见的项目文件与MVC结构优化思路解析
2016-11-04 | 阅:  转:  |  分享 
  
iOS开发中常见的项目文件与MVC结构优化思路解析

这篇文章主要介绍了iOS开发中常见的项目文件与MVC结构优化思路解析,示例代码基于传统的Objective-C,需要的朋友可以参考下

常见的项目文件介绍一、项目文件结构示意图



二、文件介绍

1.products文件夹:主要用于mac电脑开发的可执行文件,ios开发用不到这个文件2.frameworks文件夹主要用来放依赖的框架3.test文件夹是用来做单元测试的4.常用的文件夹(项目名称文件夹)(1)XXXinfo.plist文件(在该项目中为01-常见文件-Info.plist)1)简单说明是配置文件,该文件对工程做一些运行期的配置,非常重要,不能删除。在旧版本xcode创建的工程中,这个配置文件的名字就叫做info.plist。注意:因此在载入自己准备的plist文件的时候,不要以info命名。2)配置文件的属性介绍:





bundledisplayname:应用程序显示名称。如果要修改桌面上显示的文件名称,只要修改此处就可以了。(需要先删除原始的程序,然后清空一下工程,因为程序有缓存)bundleidentifer:唯一标识符(唯一的标识着一个应用程序,为了保证程序的唯一性,通常把域名倒过来写)Bundleversionsstring,short和bundleversions两个都用来表示应用程序的版本,前面的版本是正式的版本,后面的为内部版本,即公司内部开发的版本。要求提示:上传app的时候,后面更新的版本必须比之前的版本大。mainstoryboardfilebasename最主要的storyboard有两种方式修改plist配置文件:第一种方式即在如图所示的界面对配置信息进行修改。第二种方式直接点击工程,可以通过可视化界面进行设置。



补充说明:a.应用程序支持的旋转方向。四个方向,垂直-不支持颠倒-左-右(最多只支持三个方向)b.plist文件打开之后是xml文件。和字典一样,是通过键值对的形式来保存数据。在xml文件中,添加了CF前缀(2)pch文件(在该项目中为01-常见文件-Prefix.pch)1)简单说明保存的内容能够被项目中的其他所有原文件共享。通常情况下宏文件的处理,需要添加import导入头文件。以后可以把这个宏定义在这个文件中,不再需要导入头文件2)应用场景:1.用来定义一些全局的宏,2.用来导入一些全局都能用到的头文件。3.用来自定义NSlog,很消耗资源。(几乎是最消耗的),在发布的时候要把所有的打印都去掉。(补充:在开发中,分为两个阶段。一是开发调试阶段,需要打印log调试程序,如果程序处于调试阶段,系统会为我们定义一个名称叫做DEBUG的宏。二是发布阶段:不需要打印log,因为log很占用资源,并且用户看不懂log,如果程序处理发布阶段,会去除这个宏。难道在发布的时候要一个一个把NSlog都注释掉?然后在开发第二版,第三版的时候,又要把所有注释掉的NSlog都打开?对于这个问题,在.pch文件中自定义NSlog就可以很好的解决。)3)自定义NSlog在做开发的时候可以先打开pch文件,看看公司中有没有自定义NSlog。

复制代码代码如下:

//__OBJC__这个宏,在所有的.m和.mm文件中默认就定义了这个宏#ifdef__OBJC__//如果这个全局的头文件或者宏只需要在.m或者.mm文件中使用,//请把该头文件或宏写到#ifdef__OBJC__中#import#import

#ifdefDEBUG#defineNJLog(...)NSLog(__VA_ARGS__)#else#defineNJLog(...)#endif

#endif

说明:…指接收可变参数

补充:_OBJC_这个宏,在所有的.m和.mm文件中,都默认包含了这个宏,就默认会编译下面那两句条件编译语句,如果有这个宏,就编译下面的语句。

复制代码代码如下:

#import

#import

如果这个全局的头文件或者宏,只需要在.m或.mm文件中使用,请把该文件或宏写到#ifdef_ODBC_中用。注意点:建议写在条件编译里面(注意#endif)infoplist.strings的文件,跟info.plist文件的本地化相关

从代码的逐步优化看MVC

一、要求

要求完成下面一个小的应用程序。



二、一步步对代码进行优化

注意:在开发过程中,优化的过程是一步一步进行的。(如果一个人要吃五个包子才能吃饱,那么他是否直接吃第五个,前面四个不用吃就饱了?)

1.完成基本要求的代码(使用了字典转模型和xib连线)

(1)文件结构



(2)主要代码

字典转模型部分:

YYappInfo.h头文件

复制代码代码如下:

////YYappInfo.h//12-视图改进(1)////Createdbyappleon14-5-25.//Copyright(c)2014年itcase.Allrightsreserved.//

#import

@interfaceYYappInfo:NSObject@property(nonatomic,copy)NSStringname;@property(nonatomic,copy)NSStringicon;@property(nonatomic,strong,readonly)UIImageimg;

-(instancetype)initWithDict:(NSDictionary)dict;/工厂方法/+(instancetype)appInfoWithDict:(NSDictionary)dict;@end

YYappInfo.m文件

复制代码代码如下:

////YYappInfo.m//12-视图改进(1)////Createdbyappleon14-5-25.//Copyright(c)2014年itcase.Allrightsreserved.//

#import"YYappInfo.h"@interfaceYYappInfo(){UIImage_img;}@end@implementationYYappInfo-(instancetype)initWithDict:(NSDictionary)dict{if(self=[superinit]){self.name=dict[@"name"];self.icon=dict[@"icon"];}returnself;}

+(instancetype)appInfoWithDict:(NSDictionary)dict{return[[selfalloc]initWithDict:dict];}

-(UIImage)img{_img=[UIImageimageNamed:self.icon];return_img;}@end

xib部分(YYappInfoView.h文件):

注:(xib视图和YYappInfoView进行了关联,三个属性均进行了连线)

复制代码代码如下:

////YYappInfoView.h//12-视图改进(1)////Createdbyappleon14-5-25.//Copyright(c)2014年itcase.Allrightsreserved.//

#import

@interfaceYYappInfoView:UIView@property(strong,nonatomic)IBOutletUIImageViewappInfoViewimg;

@property(strong,nonatomic)IBOutletUILabelappInfoViewlab;@property(strong,nonatomic)IBOutletUIButtonappInfoViewbtn;

@end

主要功能实现部分:

YYViewController.m文件

复制代码代码如下:

////YYViewController.m//12-视图改进(1)////Createdbyappleon14-5-25.//Copyright(c)2014年itcase.Allrightsreserved.//

#import"YYViewController.h"#import"YYappInfo.h"#import"YYappInfoView.h"

@interfaceYYViewController()@property(nonatomic,strong)NSArrayapps;@end



复制代码代码如下:

//开发思路//1.加载plist文件(字典转模型提供接口)//2.使用xib文件完成单个的view//3.计算坐标,使用for循环把view展现到界面上//4.优化代码@implementationYYViewController

//get方法,懒加载-(NSArray)apps{if(!_apps){NSStringpath=[[NSBundlemainBundle]pathForResource:@"app.plist"ofType:nil];NSArrayarrayM=[NSArrayarrayWithContentsOfFile:path];NSMutableArrayappinfoarray=[NSMutableArrayarray];for(NSDictionarydictinarrayM){[appinfoarrayaddObject:[YYappInfoappInfoWithDict:dict]];}_apps=appinfoarray;}return_apps;}

-(void)viewDidLoad{[superviewDidLoad];NSLog(@"%d",self.apps.count);inttotalloc=3;CGFloatappviewW=80;CGFloatappviewH=90;CGFloatmargin=(self.view.frame.size.width-totallocappviewW)/(totalloc+1);intcount=self.apps.count;for(inti=0;i
2.对1进行优化(把数据呈现部分封装到视图)

说明:在1的基础上寻找还会有那些可以优化的部分

1)改进思路:

(1)1中主文件的66~67行对控件属性的设置能否拿到视图中进行?

(2)1中61~62行是从xib文件中读取信息的操作,且和主控制器没有什么太大的关联,能否把它也封装到视图中进行?

(3)当上述两个步骤完成后,主文件69行以后的按钮操作和按钮单击事件就显得很突兀,放在主控制器中已经不再合适,是否可以把它放到视图中进行处理

2)按照上述思路优化后的代码如下:

优化视图,在视图部分之对外提供一个接口,把数据的处理封装在内部

YYappInfoView.h文件代码:

复制代码代码如下:

////YYappInfoView.h//12-视图改进(1)////Createdbyappleon14-5-25.//Copyright(c)2014年itcase.Allrightsreserved.//

#import@classYYappInfo;@interfaceYYappInfoView:UIView

//读取//+(instancetype)appInfoView;//只对外开放一个数据接口+(instancetype)appInfoViewWithappInfo:(YYappInfo)appinfo;@end

YYappInfoView.m文件代码

说明:该文件中的属性和click等均已做了连线的操作。

复制代码代码如下:

////YYappInfoView.m//12-视图改进(1)////Createdbyappleon14-5-25.//Copyright(c)2014年itcase.Allrightsreserved.//

#import"YYappInfoView.h"#import"YYappInfo.h"//私有扩展,把属性拿进来@interfaceYYappInfoView()@property(strong,nonatomic)IBOutletUIImageViewappInfoViewimg;@property(strong,nonatomic)IBOutletUILabelappInfoViewlab;@property(strong,nonatomic)IBOutletUIButtonappInfoViewbtn;@property(strong,nonatomic)YYappInfoappinfo;

@end



复制代码代码如下:

@implementationYYappInfoView

+(instancetype)appInfoView{NSArrayarryM=[[NSBundlemainBundle]loadNibNamed:@"appInfoxib"owner:niloptions:nil];YYappInfoViewappinfoview=[arryMfirstObject];returnappinfoview;}

+(instancetype)appInfoViewWithappInfo:(YYappInfo)appinfo{YYappInfoViewappInfoView=[selfappInfoView];appInfoView.appinfo=appinfo;returnappInfoView;}

-(void)setAppinfo:(YYappInfo)appinfoc{//这里一定要记录变化_appinfo=appinfoc;self.appInfoViewimg.image=appinfoc.img;self.appInfoViewlab.www.sm136.com.text=appinfoc.name;}-(IBAction)Click{self.appInfoViewbtn.enabled=NO;//YYappInfoappinfo=self.apps[];YYappInfoappinfo=self.appinfo;UILabellab=[[UILabelalloc]initWithFrame:CGRectMake(60,450,200,20)];[labsetBackgroundColor:[UIColorlightGrayColor]];[labsetTextAlignment:NSTextAlignmentCenter];[labsetText:[NSStringstringWithFormat:@"%@成功下载",appinfo.name]];//把lab添加到父视图(即view中)[self.superviewaddSubview:lab];lab.alpha=1.0;[UIViewanimateWithDuration:2.0animations:^{lab.alpha=0;}completion:^(BOOLfinished){[labremoveFromSuperview];}];}

@end

优化后的主控制器部分

YYViewController.m文件代码

复制代码代码如下:

////YYViewController.m//12-视图改进(1)////Createdbyappleon14-5-25.//Copyright(c)2014年itcase.Allrightsreserved.//

#import"YYViewController.h"#import"YYappInfo.h"#import"YYappInfoView.h"

@interfaceYYViewController()@property(nonatomic,strong)NSArrayapps;@end



复制代码代码如下:

@implementationYYViewController

-(NSArray)apps{if(!_apps){NSStringpath=[[NSBundlemainBundle]pathForResource:@"app.plist"ofType:nil];NSArrayarrayM=[NSArrayarrayWithContentsOfFile:path];NSMutableArrayappinfoarray=[NSMutableArrayarray];for(NSDictionarydictinarrayM){[appinfoarrayaddObject:[YYappInfoappInfoWithDict:dict]];}_apps=appinfoarray;}return_apps;}

-(void)viewDidLoad{[superviewDidLoad];NSLog(@"%d",self.apps.count);inttotalloc=3;CGFloatappviewW=80;CGFloatappviewH=90;CGFloatmargin=(self.view.frame.size.www.visa158.com.width-totallocappviewW)/(totalloc+1);intcount=self.apps.count;for(inti=0;i
3.对2进一步优化(把数据处理部分拿到模型中去进行)

(1)思路:把字典转模型部分的数据处理操作,拿到模型中去处理,这样外界不需要再关心数据处理的内部细节。

(2)优化后的代码如下

YYappInfo.h文件中向外开放一个接口,返回一个处理好的数组。

复制代码代码如下:

////YYappInfo.h//12-视图改进(1)////Createdbyappleon14-5-25.//Copyright(c)2014年itcase.Allrightsreserved.//

#import

@interfaceYYappInfo:NSObject@property(nonatomic,copy)NSStringname;@property(nonatomic,copy)NSStringicon;@property(nonatomic,strong)UIImageimg;

-(instancetype)initWithDict:(NSDictionary)dict;/工厂方法/+(instancetype)appInfoWithDict:(NSDictionary)dict;+(NSArray)appinfoarray;@end

YYappInfo.m文件中的数据处理

////YYappInfo.m//12-视图改进(1)////Createdbyappleon14-5-25.//Copyright(c)2014年itcase.Allrightsreserved.//

#import"YYappInfo.h"@interfaceYYappInfo()@end



复制代码代码如下:

@implementationYYappInfo-(instancetype)initWithDict:(NSDictionary)dict{if(self=[superinit]){self.name=dict[@"name"];self.icon=dict[@"icon"];}returnself;}

+(instancetype)appInfoWithDict:(NSDictionary)dict{return[[selfalloc]initWithDict:dict];}

-(UIImage)img{_img=[UIImageimageNamed:self.icon];return_img;}

//把数据处理部分拿到模型中来处理+(NSArray)appinfoarray{NSStringpath=[[NSBundlemainBundle]pathForResource:@"app.plist"ofType:nil];NSArrayarrayM=[NSArrayarrayWithContentsOfFile:path];NSMutableArrayappinfoarray=[NSMutableArrayarray];for(NSDictionarydictinarrayM){[appinfoarrayaddObject:[YYappInfoappInfoWithDict:dict]];}returnappinfoarray;}@end

主控制器中不再需要关心数据处理的内部细节

YYViewController.m文件现在只是负责模型和视图之间的协调工作了,怎么样?差不多了吧。

复制代码代码如下:

////YYViewController.m//12-视图改进(1)////Createdbyappleon14-5-25.//Copyright(c)2014年itcase.Allrightsreserved.//

#import"YYViewController.h"#import"YYappInfo.h"#import"YYappInfoView.h"

@interfaceYYViewController()@property(nonatomic,strong)NSArrayapps;@end



复制代码代码如下:

@implementationYYViewController

-(NSArray)apps{if(!_apps){_apps=[YYappInfoappinfoarray];}return_apps;}

-(void)viewDidLoad{[superviewDidLoad];inttotalloc=3;CGFloatappviewW=80;CGFloatappviewH=90;CGFloatmargin=(self.view.www.hunanwang.net.frame.size.width-totallocappviewW)/(totalloc+1);intcount=self.apps.count;for(inti=0;i
实现效果:



4.补充说明

View的封装思路

(1)如果一个view内部的子控件比较多,一般会考虑自定义一个view,把它内部子控件的创建屏蔽起来,不让外界关心

(2)外界可以传入对应的模型数据给view,view拿到模型数据后给内部的子控件设置对应的数据

三、mvc机制简单说明



说明:

(1)在开发过程中,作为控制器处理的量级应该很轻,不该操心的不操心。协调好模型和视图就ok了,要学会当一个好老板。

(2)三个部分各司其职,数据模型只负责数据的处理,视图部分只负责把拿到的数据进行显示,两个部分都是被动的,等待着大管家控制器的调遣。

(3)在OC中,如果视图和数据模型之间有通道,那控制器是否处于失控状态呢?























献花(0)
+1
(本文系白狐一梦首藏)