1、项目分层:通过过往的一些项目经验,我们在IOS项目架构时候可以对项目进行如下图层:
OpenSourceSDK,顾名思义,就是我们引入的一些第三方的开源工具,比如github上开源项目
MySDK 就是我们自己封装的一些SDK。可以在各个项目中能用的
需要重点介绍的就是我们的MVP结构,请接着往下看
-----------------------------------------------------------------------------------------------------------------------
2、MVC与MVP区别一些看法:
1、在Anodrid项目结构上,经常听到MVC MVP的概念,两者的区别很明显,在MVP中M和V是不通信的。
2、在IOS平台上,身边的IOS开发朋友很少提到MVP,网上查找的资料也很少有把MVP和IOS关联在一起的。
3、查阅了一些资料,IOS上的MVC,M和V之间就是不通信的。这点在讨论Anodrid上是不同的。其实,MVC也好MVP也好,只是一个说法。不用太纠结。重要的是我们在项目中要知道M和V要解耦。
以下引用网上的两张图片,可以帮更好的理解
更多MVP,MVC讨论请点击链接:
MVP MVC的认识:http://blog.csdn.net/sbvfhp/article/details/47848403
-----------------------------------------------------------------------------------------------------------------------
3、我自己项目的结构图如下(有更好的意见请大家指出)
-----------------------------------------------------------------------------------------------------------------------
4、MVP里需要重点考虑的问题
Controller需要考虑的重点:
对View 和 Model之间的一个协调,调度。
以下是一个列表的显示(包含下拉刷新,加载更多),核心代码也就几十行。
[objc]
view plain
copy
- @interface WorksViewController () {
- IBOutlet UICollectionView *_collectionView;
- WorksRequest *_worksRequest;
- NSInteger _page;
- BOOL _isEnd;
- NSMutableArray *_data;
- }
- @end
- @implementation WorksViewController
- - (void)viewDidLoad {
- [super viewDidLoad];
- [_collectionView registerNib:[UINib nibWithNibName:@"WorksCell" bundle:nil] forCellWithReuseIdentifier:@"WorksCell"];
- _data = [NSMutableArray new];
- _worksRequest = [[WorksRequest alloc]init];
- _collectionView.header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{
- [self refresh];
- }];
- _collectionView.footer = [MJRefreshAutoNormalFooter footerWithRefreshingBlock:^{
- [self loadMore];
- }];
- [_collectionView.header beginRefreshing];
- }
- -(void)clean {
- for (WorksDB *worksDB in _data) {
- [worksDB MR_deleteEntity];
- }
- [[NSManagedObjectContext MR_defaultContext]MR_saveToPersistentStoreWithCompletion:nil];
- [_data removeAllObjects];
- }
- -(void)refresh {
- _page = 1;
- _isEnd = false;
- _worksRequest.page = _page;
- [_worksRequest execute:^(id cacheData){
- if(cacheData) {
- [_data addObjectsFromArray:cacheData];
- }
- } requestSuccess:^(id responseObject) {
- [_collectionView.header endRefreshing];
- WorksListModel *worksListModel = [[WorksListModel alloc]initFromDictionary:responseObject];
- if(worksListModel.errNo.intValue == 0) {
- _page++;
- _isEnd = worksListModel.isEnd.boolValue;
- [self clean];
- [_data addObjectsFromArray:worksListModel.data];
- [_collectionView reloadData];
- }
- } failure:^(NSError *error) {
- [self.view makeToast:@"网络错误"];
- [_collectionView.header endRefreshing];
- }];
- }
- -(void)loadMore {
- if(!_isEnd) {
- _worksRequest.page = _page;
- [_worksRequest execute:^(id responseObject) {
- [_collectionView.footer endRefreshing];
- WorksListModel *worksListModel = [[WorksListModel alloc]initFromDictionary:responseObject];
- if(worksListModel.errNo.intValue == 0) {
- _page++;
- _isEnd = worksListModel.isEnd.boolValue;
- [_data addObjectsFromArray:worksListModel.data];
- [_collectionView reloadData];
- }
- } failure:^(NSError *error) {
- [self.view makeToast:@"网络错误"];
- [_collectionView.footer endRefreshing];
- }];
- }
- }
- #pragma datasource & delegate
- - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
- return _data.count;
- }
- - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
- WorksCell *worksCell = [collectionView dequeueReusableCellWithReuseIdentifier:@"WorksCell" forIndexPath:indexPath];
- worksCell.worksDB = [_data objectAtIndex:indexPath.row];
- return worksCell;
- }
- - (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
- return 1;
- }
- - (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
- CGFloat width = (self.view.frame.size.width - 20) / 3;
- return CGSizeMake(width, width * 1.5);
- }
- - (UIEdgeInsets)collectionView:(UICollectionView*)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
- return UIEdgeInsetsMake(5, 5, 5, 5);
- }
- - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumLineSpacingForSectionAtIndex:(NSInteger)section {
- return 5.0;
- }
- - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
- return 5.0;
- }
- @end
Model考虑的重点:
1)网络,解析通信:AFNetworking(取代ASI)通信,解析可以考虑使用MJExtension
2)数据缓存: CoreData(可以用MagicalRecord框架) 或者直接操作sql(可以选用FMDB框架)。这里CoreData可能效率上没有直接写sql高,但是在一些框架的基础上代码非常简洁,面向对象的思想比较强
如下是对Request的一个操作
[objc]
view plain
copy
- @implementation BaseRequest
- - (instancetype)init {
- self = [super init];
- if (self) {
- _params = [NSMutableDictionary new];
- _method = RequestMethodGet;
- }
- return self;
- }
- -(void)setParam:(NSString *)name value:(NSString *)value {
- _params[name] = value;
- }
- -(void)execute:(void (^)(id responseObject))requestSuccess failure:(void (^)(NSError *error))requestFailure {
- AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
- if(_acceptableContentTypes) {
- manager.responseSerializer.acceptableContentTypes = _acceptableContentTypes;
- }
- if(_method == RequestMethodGet) {
- [manager GET:_url parameters:_params success:^(AFHTTPRequestOperation *operation, id responseObject){
- requestSuccess(responseObject);
- } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
- requestFailure(error);
- }];
- }
- else if(_method == RequestMethodPost){
- [manager POST:_url parameters:_params success:^(AFHTTPRequestOperation *operation, id responseObject){
- requestSuccess(responseObject);
- } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
- requestFailure(error);
- }];
- }
- }
- -(void)execute:(void (^)(id cacheData))cacheData requestSuccess:(void (^)(id responseObject))requestSuccess failure:(void (^)(NSError *error))requestFailure {
- cacheData([self getCacheData]);
- [self execute:requestSuccess failure:requestFailure];
- }
- -(id)getCacheData {
- return nil;
- }
- @end
[objc]
view plain
copy
- @implementation WorksRequest
- - (instancetype)init {
- self = [super init];
- if (self) {
- self.acceptableContentTypes = [NSSet setWithObject:@"text/html"];
- self.page = 1;
- self.method = RequestMethodPost;
- }
- return self;
- }
- -(void)setPage:(NSInteger)page {
- _page = page;
- [self setParam:@"page" value:[NSString stringWithFormat:@"%ld", (long)_page]];
- }
- -(id)getCacheData {
- return [WorksDB MR_findAllSortedBy:@"worksid" ascending:FALSE];
- }
- @end
View涉及的重点:重点应该体现封装,相同的代码,或者xib尽量抽取,达到重用
布局的方法有xib,storyboard,代码,应该在项目中灵活选用
贯穿项目中的还会用到一些,
block,这里可以考虑一下BlockKit这个框架,对block的一个封装,代码更简洁
SDWebImage图片框架
GCD/OperationQueue多线程
单例:请查看链接:http://blog.csdn.net/sbvfhp/article/details/47861453
KVO:
未完,待续......
-----------------------------------------------------------------------------------------------------------------------
版权声明:本文为博主原创文章,未经博主允许不得转载。