美文网首页iOS-项目类iOS开发111
从零开始搭建iOS项目框架

从零开始搭建iOS项目框架

作者: 深圳张学友 | 来源:发表于2017-03-31 14:15 被阅读1269次

    APP项目搭建

    上周个人刚搭建完的项目框架,在这分享一下,主要还是采用MVC设计模式,没有使用storyboard,纯代码搭的界面。

    1.新建工程

    1.1 新建项目

    删除文件
    • 删除无用的文件(Main.storyboard,ViewController)
    • 删除plist文件中Main storyboard file base name一项
    • appdelegate进行修改
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
         self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        self.window.backgroundColor = [UIColor whiteColor];
        
    
        [self.window makeKeyAndVisible];
    
    }
    

    1.2 创建不同的target管理工程

    有时候我们需要多个版本,开发版、测试版或者线上版,或因渠道不同需要区分企业版,AppStore版等。这个时候使用target来管理就比较方便

    1.2.1 生成

    多target生成

    1.2.2 修改名字

    需要修改下名字target、scheme、info.plist三项的名字,主要用来区分下版本

    注意:修改了info.plist名字需要修改新建的target的配置信息文件,让其能找到info.plist文件

    1.2.3 修改下工程配置文件


    就可以这样使用了:
    #if DEVELOPMENT
        NSLog(@"development");
    #else
        NSLog(@"release");
    #endif
    

    使用方法可参考:多个Target管理

    1.3 导入CocoaPods管理依赖库

    自从CocoaPods升级到1.0.1之后,为多个target导入依赖库,之前的link_with语法不能用了,使用如下方法:

    source 'https://github.com/CocoaPods/Specs.git'
    platform :ios, ‘7.0’
    
    # ruby语法
    # target数组 如果有新的target直接加入该数组
    targetsArray = [‘MyApp’, ‘MyAppTest’]
    # 循环
    targetsArray.each do |t|
        target t do
            pod 'MJRefresh', '~> 3.1.12'
            pod 'Masonry', '~> 0.6.1'
            pod 'AFNetworking', '~> 3.1.0'
            pod 'MJExtension'
            pod 'MBProgressHUD'
            pod 'SDWebImage'
    
    
    
        end
    end
    

    使用方法可参考:CocoaPods安装教程

    1.4 info.plist配置

    1.4.1 开启http的访问权限

    info.plist 中添加以下


    http访问

    1.4.2 添加应用白名单

    iOS9之后分享等必须添加白名单后才可以打开相关应用。字段值为LSApplicationQueriesSchemes


    项目目录

    2.2 导入需要用的第三方库

    先使用CocoaPods导入项目中一些常用的第三方库,后续再根据需求导入,有些无法用CocoaPods导入的或者是一些需要修改库中代码的拖入到工程中Vender文件夹中

    2.3 创建pch文件

    这个文件用来包含全局使用的头文件,例如:
    1.第三方头文件
    2.全局宏定义
    3.自定义的头文件包含主题、网络请求地址、全局方法、key等

    使用方法参考: Pch 文件的正确使用

    3 全局的宏定义

    具体方法大家可下载demo看下

    宏定义

    3.1 全局配置参数DefineMacro

    全局宏定义包含一些屏幕宽高、iOS版本、手机类型等

    #define SCREEN_WIDTH   [UIScreen mainScreen].bounds.size.width
    #define SCREENH_HEIGHT [UIScreen mainScreen].bounds.size.height
    //随机颜色
    #define KRandomColor [UIColor colorWithRed:arc4random_uniform(256)/255.0 green:arc4random_uniform(256)/255.0 blue:arc4random_uniform(256)/255.0 alpha:1.0]
    

    3.2 样式定义DefineTheme

    主要包含样式上的定义,主题颜色、各类字体大小颜色、控件大小等

    //颜色
    #define TITLE_COLOR [UIColor blackColor]//标题颜色
    #define TEXT_COLOR [UIColor grayColor]//正文颜色
    #define TIPTEXT_COLOR UIColorFromRGB(0x888888)//提示语文本颜色
    #define MAIN_GROUNDCOLOR UIColorFromRGB(0xF98B1B)//主题景色
    #define BACKGROUNDCOLOR UIColorFromRGB(0xF7F7F7)//背景颜色
    //字体大小
    #define TITLEFONT [UIFont systemFontOfSize:18]
    #define TEXTFONT [UIFont systemFontOfSize:16]
    #define TIPTEXTFONT [UIFont systemFontOfSize:12]
    
    

    3.3 API地址DefineRequest

    访问的地址,各个接口的查询

    #if DEVELOPMENT //***************开发版本*************
    //****************测试环境***********
    //app服务重构测试
    //#define BaseURLString   @"http://www-test.baidu.com/rest/post"//beta
    //#define BaseURLString @"http://docker-branch02-web-tomcat.baidu.com:8080/rest/post"//分之域名
    //****************开发环境(个人服务器)************
    //后台XXX
    #define BaseURLString  @"http://192.168.1.175:8080/baidu/rest/post"
    #else          //**************生产版本**************
    #define BaseURLString @"https://www.baidu.com/rest/post"
    #endif
    
    //****************接口说明************
    //获取用户信息
    #define Request_type_getUserInfo @"getUserInfo"
    //首页广告
    #define Request_type_queryBannerByType @"queryBannerByType"
    
    

    4. 初期代码编写

    公共类

    4.1 Category

    4.1.1 Method swizzling

    为Controller添加一些方法,即可省略继承baseViewController的麻烦,还可以对各工厂类进行操作

    #import "UIViewController+swizzling.h"
    #import <objc/runtime.h>
    
    @implementation UIViewController (swizzling)
    
    + (void)load {
        Method fromMethod = class_getInstanceMethod([self class], @selector(viewDidLoad));
        Method toMethod = class_getInstanceMethod([self class], @selector(swizzlingViewDidLoad));
      
        if (!class_addMethod([self class], @selector(swizzlingViewDidLoad), method_getImplementation(toMethod), method_getTypeEncoding(toMethod))) {
            method_exchangeImplementations(fromMethod, toMethod);
        }
    }
    
    // 我们自己实现的方法,也就是和self的viewDidLoad方法进行交换的方法。
    - (void)swizzlingViewDidLoad {
        NSString *str = [NSString stringWithFormat:@"%@", self.class];
        if(![str containsString:@"UI"]){
            NSLog(@"统计打点 : %@", self.title);
        }
        [self swizzlingViewDidLoad];
    }
    @end
    

    4.1.2 appDelegate添加category

    用以简化appDelegate中代码

    AppDelegate+ViewController.h
    - (void)setAppWindows
    {
        self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
        self.window.backgroundColor = [UIColor whiteColor];
        
        [[UINavigationBar appearance] setTitleTextAttributes:@{NSForegroundColorAttributeName: [UIColor whiteColor]}];
        
        [self.window makeKeyAndVisible];
    
    }
    
    - (void)setRootViewController
    {
        AppDelegate *app = (AppDelegate *)[[UIApplication sharedApplication] delegate];
        app.window.rootViewController = [[RootTabViewController alloc] init];
    
    }
    
    AppDelegate+AppService.h

    需要处理的各类服务都可以添加在这

    /**
     *  系统配置
     */
    - (void)systemConfigration;
    
    /**
     *  友盟注册
     */
    - (void)registerUmeng;
    /**
     *  个推注册
     */
    
    - (void)registerGeiTui;
    
    /**
     *  检查更新
     */
    - (void)checkAppUpDataWithshowOption:(BOOL)showOption;
    
    /**
     *  获取用户信息
     */
    - (void)getUserData;
    

    4.2 DataMange

    • 存放对文件的处理方法,文件的路径
    • 数据库的处理
    • NSUserDefault的处理

    4.3 Other

    建一个类存放比较杂乱的一些公共方法

    /**验证该字符串是否是6-16位字母和数字组合*/
    + (BOOL)checkIsDigitalAndLetter:(NSString *)string;
    /**利用正则表达式验证手机号码*/
    + (BOOL)checkTel:(NSString *)str;
    /**利用正则表达式验证邮箱*/
    + (BOOL)checkEmail:(NSString *)email;
    

    4.4 UITools

    一些公共控件的封装,常用的一些控件进行封装(弹窗、广告轮播等),方便以后统一修改

    4.4.1 NavigationViewController封装

    @interface LWTNavigationViewController ()<UINavigationControllerDelegate>
    
    @property (nonatomic, weak) id popDelegate;
    
    @end
    
    @implementation LWTNavigationViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.popDelegate = self.interactivePopGestureRecognizer.delegate;
        self.delegate = self;
    
        //navigationBar样式设置
        self.navigationBar.barTintColor = MAIN_GROUNDCOLOR;
        [self.navigationBar setTitleTextAttributes:@{NSForegroundColorAttributeName : WHITCOLOR, NSFontAttributeName : [UIFont boldSystemFontOfSize:18]}];
        [self.navigationBar setTintColor:WHITCOLOR];    // Do any additional setup after loading the view.
    }
    
    //解决手势失效问题
    - (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
        if (viewController == self.viewControllers[0]) {
            self.interactivePopGestureRecognizer.delegate = self.popDelegate;
        }else{
            self.interactivePopGestureRecognizer.delegate = nil;
        }
    }
    
    //push时隐藏tabbar
    - (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
        if (self.viewControllers.count > 0) {
            viewController.hidesBottomBarWhenPushed = YES;
        }
        [super pushViewController:viewController animated:animated];
    }
    
    //设置样式
    - (UIStatusBarStyle)preferredStatusBarStyle
    {
        return UIStatusBarStyleLightContent;
    }
    
    //设置返回按钮样式
    - (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
    {
        
        UIBarButtonItem *backBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"返回" style:UIBarButtonItemStylePlain target:self action:@selector(backBarButtonItemAction)];
        viewController.navigationItem.backBarButtonItem = backBarButtonItem;
        
    }
    
    - (void)backBarButtonItemAction
    {
        [self popViewControllerAnimated:YES];
    }
    
    
    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }
    @end
    

    4.4.2 tabBarController封装

    #import "RootTabViewController.h"
    #import "LWTNavigationViewController.h"
    
    # define kTabbarSelectTintColor [UIColor brownColor]
    # define kTabbarNormalTintColor [UIColor blackColor]
    
    @interface RootTabViewController ()<UITabBarControllerDelegate>
    
    @end
    
    @implementation RootTabViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        [self buildUI];
        // Do any additional setup after loading the view.
    }
    
    /**构建视图*/
    - (void)buildUI{
        
        self.tabBar.translucent     = NO;
        self.tabBar.backgroundImage = [CommonMethods createImageWithColor:[UIColor clearColor]];
        self.tabBar.shadowImage     = [CommonMethods createImageWithColor:[UIColor grayColor]];
        
        NSArray * normalItems       = @[@"home_gray",@"circle_gray",@"me"];
        NSArray * selectItmes       = @[@"home_blue",@"circle_blue",@"me_blue"];
        
        NSArray * controllClass     = @[@"HomePageViewController",@"MessageViewController",@"MyViewController"];
        self.delegate               = self;
        NSArray * itemTitles        = @[@"首页",@"信息",@"我"];
        NSMutableArray * controllers = [[NSMutableArray alloc]init];
        for (int i = 0; i < normalItems.count; i++)
        {
            UIViewController * homeview =[[NSClassFromString(controllClass[i]) alloc]init];
            LWTNavigationViewController * navigation =[[LWTNavigationViewController alloc]initWithRootViewController:homeview];
            navigation.tabBarItem.image                     = [[UIImage imageNamed:normalItems[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
            navigation.tabBarItem.selectedImage             = [[UIImage imageNamed:selectItmes[i]] imageWithRenderingMode:UIImageRenderingModeAlwaysOriginal];
            navigation.tabBarItem.titlePositionAdjustment   = UIOffsetMake(0,-3);
            [controllers addObject:navigation];
            
            // 设置文字的样式
            NSMutableDictionary *textAttrs                  = [NSMutableDictionary dictionary];
            textAttrs[NSForegroundColorAttributeName]       = kTabbarNormalTintColor;
            NSMutableDictionary *selectTextAttrs            = [NSMutableDictionary dictionary];
            selectTextAttrs[NSForegroundColorAttributeName] = kTabbarSelectTintColor;
            [homeview.tabBarItem setTitleTextAttributes:textAttrs forState:UIControlStateNormal];
            [homeview.tabBarItem setTitleTextAttributes:selectTextAttrs forState:UIControlStateSelected];
            // 设置tabbaritem 的title
            navigation.tabBarItem.title                     = itemTitles[i];
        }
        self.viewControllers = controllers;
    }
    @end
    

    4.5 第三方库的封装

    4.5.1 网络框架

    //基本参数设置
    + (AFHTTPSessionManager *)httpManager{
        //获取请求对象
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        // 设置请求格式
        manager.requestSerializer = [AFJSONRequestSerializer serializer];
        // 设置返回格式
        manager.responseSerializer = [AFHTTPResponseSerializer serializer];
        [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];
        [manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
        manager.requestSerializer.timeoutInterval = RequestTimeOut;
        return manager;
    }
    
    //请求处理
    + (void)postParameters:(id)parameters
                   success:(void (^)(NSDictionary *resDict))success
                   failure:(void (^)(NSError *error))failure
    {
        
        //    if ([[AFNetworkReachabilityManager sharedManager] networkReachabilityStatus] <= 0) {
        //        [MBProgressHUD showMessageInWindow:@"网络无连接" afterDelayHide:AfterDelayHide];
        //        return;
        //    }
        AFHTTPSessionManager *manager = [self httpManager];
        //开始请求
        [manager POST:BaseURLString
           parameters:parameters
             progress:^(NSProgress * _Nonnull uploadProgress) {
             }
              success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
                  NSMutableDictionary *resDict = (NSMutableDictionary *)[responseObject mj_JSONObject];
    //              NSDictionary *dict = [HttpManager checkResultVaild:resDict withFunction:parameters[@"function"]];
                  
                 //这里可以处理数据 针对接口返回的特定参数进行处理,如单点登录等需求
                  NSLog(@"\n接口:%@\n返回数据:%@",parameters[@"function"],[[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding]);
                  
                  success(resDict);
              }
              failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
                  failure(error);
                  NSLog(@"\n当前接口:%@\n错误信息:%@",parameters[@"function"],error);
              }];
    }
    
    

    4.5.2 其他第三方

    UM、HUD等很多第三方框架,都需要进行封装,针对自己app需求进行配置,使用起来就比较方便。

    Demo

    有什么建议可以提出来,有更好的欢迎探讨,不定期更新
    demo下载

    参考

    文中的内容有参考过以下文章,大家可以参考下
    多个Target管理
    CocoaPods安装教程
    Pch 文件的正确使用
    iOS黑魔法-Method Swizzling
    手把手教你iOS项目基本框架

    相关文章

      网友评论

      本文标题:从零开始搭建iOS项目框架

      本文链接:https://www.haomeiwen.com/subject/xacvottx.html