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 生成
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 中添加以下
1.4.2 添加應用白名單
iOS9之后分享等必須添加白名單后才可以打開相關應用。字段值為LSApplicationQueriesSchemes

1.4.3 其他
設置分享到微信、微博啊等URL Types
2.項目模塊化
2.1 分類各模塊
分類具體按照業務需求去歸類,開發前把大體的分類號,主體的文件夾建立真實的文件夾,再把真實的文件夾拖到項目中,這樣的好處是,避免了在項目中創建虛擬文件夾,然后導致各類文件都放在一塊,不方便查找。
大致分類:
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"http://beta
//#define BaseURLString @"http://docker-branch02-web-tomcat.baidu.com:8080/rest/post"http://分之域名
//****************開發環境(個人服務器)************
//后臺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項目基本框架