• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>

            專職C++

            不能停止的腳步

              C++博客 :: 首頁 :: 聯系 :: 聚合  :: 管理
              163 Posts :: 7 Stories :: 135 Comments :: 0 Trackbacks

            常用鏈接

            留言簿(28)

            我參與的團隊

            搜索

            •  

            最新評論

            閱讀排行榜

            評論排行榜

            原文:http://www.cnblogs.com/zjoch/p/6018289.html
            一.前言

            iOS開發更新APP我覺得是比較坑的就是審核時間比較長,審核比較嚴,對于剛入行的小伙伴來說,雷區比較多;所以熱更新是比較重要的;
            大家也許會發現我們常用的QQ現在下來也就一百多兆,但是用了幾個月后發現QQ在手機上占有一個多G的內存,特別是手機內存比較小的小伙伴,這是因為你在使用過程中,有一些功能是你下載下來的;

            二.創建Framework

            1.新建項目

            新建一個Cocoa Touch Framework項目,然后在這個項目里面寫你的新的功能,比如我創建了一個控制器,在控制器里面加載一張圖和一個label;
            1. <span style="font-size:18px;">- (void)uiConfig{  
            2.     self.title = @"這是功能2";  
            3.       
            4.     UIImageView *imageView = [[UIImageView alloc]init];  
            5.     imageView.frame = CGRectMake(0, 0, ScreenWidth, ScreenHeight);  
            6.     NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://img4.duitang.com/uploads/item/201405/31/20140531174207_hH5u4.thumb.700_0.jpeg"]];  
            7.     imageView.image = [UIImage imageWithData:data];  
            8.     [self.view addSubview:imageView];  
            9.       
            10.     UILabel *label = [[UILabel alloc]init];  
            11.     label.backgroundColor = [UIColor clearColor];  
            12.     label.frame = CGRectMake(0, (ScreenHeight - 100)/2, ScreenWidth, 100);  
            13.     label.numberOfLines = 0;  
            14.     label.text = @"這是功能2這是功能2這是功能2這是功能2這是功能2這是功能2這是功能2這是功能2這是功能2這是功能2這是功能2這是功能2這是功能2這是功能2這是功能2";  
            15.     [self.view addSubview:label];  
            16. }</span>  

            2.添加Aggregate

            在TARGETS里面新建一個Aggregate

            3.添加Run Script腳本

            4.腳本源碼

            1. <span style="font-size:18px;"># Sets the target folders and the final framework product.  
            2. # 如果工程名稱和Framework的Target名稱不一樣的話,要自定義FMKNAME  
            3. # 例如: FMK_NAME = "MyFramework"  
            4. FMK_NAME=${PROJECT_NAME}  
            5. # Install dir will be the final output to the framework.  
            6. # The following line create it in the root folder of the current project.  
            7. INSTALL_DIR=${SRCROOT}/Products/${FMK_NAME}.framework  
            8. # Working dir will be deleted after the framework creation.  
            9. WRK_DIR=build  
            10. DEVICE_DIR=${WRK_DIR}/Release-iphoneos/${FMK_NAME}.framework  
            11. SIMULATOR_DIR=${WRK_DIR}/Release-iphonesimulator/${FMK_NAME}.framework  
            12. # -configuration ${CONFIGURATION}  
            13. # Clean and Building both architectures.  
            14. xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphoneos clean build  
            15. xcodebuild -configuration "Release" -target "${FMK_NAME}" -sdk iphonesimulator clean build  
            16. # Cleaning the oldest.  
            17. if [ -d "${INSTALL_DIR}" ]  
            18. then  
            19. rm -rf "${INSTALL_DIR}"  
            20. fi  
            21. mkdir -p "${INSTALL_DIR}"  
            22. cp -R "${DEVICE_DIR}/" "${INSTALL_DIR}/"  
            23. # Uses the Lipo Tool to merge both binary files (i386 + armv6/armv7) into one Universal final product.  
            24. lipo -create "${DEVICE_DIR}/${FMK_NAME}" "${SIMULATOR_DIR}/${FMK_NAME}" -output "${INSTALL_DIR}/${FMK_NAME}"  
            25. rm -r "${WRK_DIR}"  
            26. open "${INSTALL_DIR}"  
            27. </span>  

            5.運行打包

            運行工程,將生成的framework包壓縮zip,然后上傳服務器;
            例如:http://7xqdun.com1.z0.glb.clouddn.com/FunctionZFJ1.framework.zip
             

            三.創建項目

            在項目中我們主要是下載和讀取framework包;我們先要獲取功能列表,在此我在本地寫了一個功能列表,大家如果用得到可以將功能列表存放在服務器上;

            1.創建功能列表數據

            我添加了四個功能模塊,存在NSUserDefaults里面;其中功能1和功能2有下載地址,其他的沒有;功能1是個NSObject,功能2直接是一個控制器;
            isopen:1表示打開,0表示關閉;
            1. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {  
            2.     // Override point for customization after application launch.  
            3.     self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];  
            4.     self.window.backgroundColor = [UIColor whiteColor];  
            5.     [self.window makeKeyAndVisible];  
            6.       
            7.     //添加假的功能列表  
            8.     NSArray *functionList = [USER_DEFAULT objectForKey:@"functionList"];  
            9.     if(functionList==nil || functionList.count==0){  
            10.         NSArray *titleArr  = @[@"功能1",@"功能2",@"功能3",@"功能4"];  
            11.         NSArray *className = @[@"HotUpdateControl",@"ZFJViewController",@"",@""];  
            12.         NSArray *classType = @[@"NSObject",@"UIViewController",@"",@""];  
            13.         NSArray *downUrl   = @[  
            14.                                @"http://7xqdun.com1.z0.glb.clouddn.com/HotMudel.framework.zip",  
            15.                                @"http://7xqdun.com1.z0.glb.clouddn.com/FunctionZFJ1.framework.zip",  
            16.                                @"",  
            17.                                @""];  
            18.         NSMutableArray *functionArr = [[NSMutableArray alloc]init];  
            19.         for (int i = 0; i<titleArr.count; i++) {  
            20.             NSMutableDictionary *dict = [[NSMutableDictionary alloc]init];  
            21.             [dict setObject:titleArr[i] forKey:@"name"];  
            22.             [dict setObject:className[i] forKey:@"classname"];  
            23.             [dict setObject:classType[i] forKey:@"classtype"];  
            24.             [dict setObject:@(i) forKey:@"mid"];  
            25.             [dict setObject:@"0" forKey:@"isopen"];//0 未開啟  1開啟了  
            26.             [dict setObject:downUrl[i] forKey:@"downurl"];  
            27.             [functionArr addObject:dict];  
            28.         }  
            29.         [USER_DEFAULT setObject:functionArr forKey:@"functionList"];  
            30.         [USER_DEFAULT synchronize];  
            31.     }  
            32.       
            33.     DynamicViewController *dvc = [[DynamicViewController alloc]init];  
            34.     UINavigationController *nvc = [[UINavigationController alloc]initWithRootViewController:dvc];  
            35.     self.window.rootViewController = nvc;  
            36.       
            37.     return YES;  
            38. }  

            2.展示功能列表

            在功能列表主要用于展示所有打開過的功能,也就是isopen為1的所有功能;
            a.獲取本地所有打開的數據,然后在tableview上顯示
            1. - (void)getDataBase{  
            2.     [self.dataArray removeAllObjects];  
            3.     NSArray *functionList = [USER_DEFAULT objectForKey:@"functionList"];  
            4.     for (NSDictionary *dict in functionList) {  
            5.         NSInteger isopen = [dict[@"isopen"] integerValue];  
            6.         if(isopen==1){  
            7.             [self.dataArray addObject:dict];  
            8.         }  
            9.     }  
            10.     [self.tableview reloadData];  
            11. }  

            b.點擊對于的tableviewcell 的時候跳轉對應的framework讀取出來的方法
            注意,我將不同的framework存放在不同的文件夾下,以mid作為區分;
            1. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{  
            2.     [tableView deselectRowAtIndexPath:indexPath animated:YES];  
            3.     NSDictionary *dict = self.dataArray[indexPath.row];  
            4.     //獲取framework的路徑名,我已mid區分  
            5.     NSString *destinationPath = [NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"/Documents/FunctionZFJ%@",dict[@"mid"]]];  
            6.     NSArray* arrFramework = [self getFilenamelistOfType:@"framework" fromDirPath:destinationPath];  
            7.     NSString *bundlePath = [NSString stringWithFormat:@"%@/%@",destinationPath,[arrFramework lastObject]];  
            8.     if (![[NSFileManager defaultManager] fileExistsAtPath:bundlePath]) {  
            9.         NSLog(@"文件不存在");  
            10.         return;  
            11.     }  
            12.       
            13.     NSBundle *bundle = [NSBundle bundleWithPath:bundlePath];  
            14.     if (!bundle || ![bundle load]) {  
            15.         NSLog(@"bundle加載出錯");  
            16.     }  
            17.       
            18.     NSString *className = dict[@"classname"];  
            19.     NSString *classtype = dict[@"classtype"];  
            20.       
            21.     Class loadClass = [bundle classNamed:className];  
            22.     if (!loadClass) {  
            23.         NSLog(@"獲取失敗");  
            24.         return;  
            25.     }  
            26.       
            27.     if([classtype isEqualToString:@"NSObject"]){  
            28.         NSObject *bundleObj = [loadClass new];  
            29.         NSArray *arrVc = [bundleObj performSelector:@selector(getVcs)];  
            30.         TabController *tvc = [[TabController alloc]initwithVcArray:arrVc];  
            31.         [self.navigationController pushViewController:tvc animated:YES];  
            32.     }else if([classtype isEqualToString:@"UIViewController"]){  
            33.         UIViewController *uvc = (UIViewController *)[loadClass new];  
            34.         [self.navigationController pushViewController:uvc animated:YES];  
            35.     }  
            36. }  

            c.效果圖
             

            3.更多功能

            在這里我們可以打開或者關閉某個功能;
            a.獲取所以功能,包括打開或者關閉狀態的;然后在tableview上顯示;
            1. <span style="font-size:18px;">#pragma mark - 獲取全部數據  
            2. - (void)getDataBase{  
            3.     [self.dataArray removeAllObjects];  
            4.       
            5.     NSArray *functionList = [USER_DEFAULT objectForKey:@"functionList"];  
            6.     NSMutableArray *openYES = [[NSMutableArray alloc]init];  
            7.     NSMutableArray *openNO = [[NSMutableArray alloc]init];  
            8.     for (NSDictionary *dict in functionList) {  
            9.         NSMutableDictionary *muDict = [[NSMutableDictionary alloc]initWithDictionary:dict];  
            10.         NSInteger isopen = [muDict[@"isopen"] integerValue];  
            11.         if(isopen==1){  
            12.             //已經打開的功能  
            13.             [openYES addObject:muDict];  
            14.         }else{  
            15.             //沒有打開的功能  
            16.             [openNO addObject:muDict];  
            17.         }  
            18.     }  
            19.       
            20.     [self.dataArray addObject:openNO];  
            21.     [self.dataArray addObject:openYES];  
            22.       
            23.     [self.tableview reloadData];  
            24. }</span>  

            b.打開功能
            打開某個功能就是下載對應的framework,把下載下來的zip包進行解壓一下然后獲取到framework,接著刪除zip包,把framework放在對于的目錄下;最后改變本地列表功能的狀態;
            1. <span style="font-size:18px;">#pragma mark - 開啟某個功能 先下載數據  
            2. - (void)SSZipArchiveDataBaseWithDict:(NSMutableDictionary *)dict{  
            3.     NSString *requestURL = dict[@"downurl"];  
            4.     if(requestURL==nil || requestURL.length==0){  
            5.         self.progresslabel.text = [NSString stringWithFormat:@"%@-沒有下載地址,不能開啟!",dict[@"name"]];  
            6.         UIAlertController *alertController = [UIAlertController alertControllerWithTitle:@"提示" message:@"沒有下載地址,不能開啟" preferredStyle:UIAlertControllerStyleAlert];  
            7.         UIAlertAction *sureBtn = [UIAlertAction actionWithTitle:@"確定" style:UIAlertActionStyleDefault handler:nil];  
            8.         [alertController addAction:sureBtn];  
            9.         [self presentViewController:alertController animated:YES completion:nil];  
            10.         return;  
            11.     }  
            12.     //下載保存的路徑  
            13.     NSString *savedPath = [NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"/Documents/FunctionZFJ%@.framework.zip",dict[@"mid"]]];  
            14.     AFHTTPRequestSerializer *serializer = [AFHTTPRequestSerializer serializer];  
            15.     NSMutableURLRequest *request = [serializer requestWithMethod:@"POST" URLString:requestURL parameters:nil error:nil];  
            16.     AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:request];  
            17.     [operation setOutputStream:[NSOutputStream outputStreamToFileAtPath:savedPath append:NO]];  
            18.     [operation setDownloadProgressBlock:^(NSUInteger bytesRead, long long totalBytesRead, long long totalBytesExpectedToRead) {  
            19.         float progress = (float)totalBytesRead / totalBytesExpectedToRead;  
            20.         self.progresslabel.text = [NSString stringWithFormat:@"%@下載進度:%.2f",dict[@"name"],progress];  
            21.     }];  
            22.     [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {  
            23.         NSLog(@"下載成功");  
            24.         NSString *destinationPath = [NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"/Documents/FunctionZFJ%@",dict[@"mid"]]];  
            25.         //對下載下來的ZIP包進行解壓  
            26.         BOOL isScu = [SSZipArchive unzipFileAtPath:savedPath toDestination:destinationPath];  
            27.         if(isScu){  
            28.             NSLog(@"解壓成功");  
            29.             NSFileManager *fileMgr = [NSFileManager defaultManager];  
            30.             BOOL bRet = [fileMgr fileExistsAtPath:savedPath];  
            31.             if (bRet) {  
            32.                 [fileMgr removeItemAtPath:savedPath error:nil];//解壓成功后刪除壓縮包  
            33.             }  
            34.             [dict setValue:@"1" forKey:@"isopen"];  
            35.             [self updataBaseWithDict:dict];//解壓成功后更新本地功能列表狀態  
            36.         }else{  
            37.             NSLog(@"解壓失敗 --- 開啟失敗");  
            38.         }  
            39.           
            40.     } failure:^(AFHTTPRequestOperation *operation, NSError *error) {  
            41.         NSLog(@"下載失敗 --- 開啟失敗");  
            42.           
            43.     }];  
            44.     [operation start];  
            45. }  
            46. </span>  
            更新本地數據
            1. <span style="font-size:18px;">#pragma mark - 更新本地數據  
            2. - (void)updataBaseWithDict:(NSMutableDictionary *)dict{  
            3.     NSInteger mid = [dict[@"mid"] integerValue];  
            4.     NSMutableArray *functionList = [USER_DEFAULT objectForKey:@"functionList"];  
            5.     NSMutableArray *dataArr = [[NSMutableArray alloc]initWithArray:functionList];  
            6.     [dataArr replaceObjectAtIndex:mid withObject:dict];  
            7.     [USER_DEFAULT setObject:dataArr forKey:@"functionList"];  
            8.     BOOL isScu = [USER_DEFAULT synchronize];  
            9.     if(isScu){  
            10.         [self getDataBase];//重新獲取數據 更新列表  
            11.         if(self.refreshData){  
            12.             self.refreshData();  
            13.         }  
            14.     }else{  
            15.         NSLog(@"c操作失敗");  
            16.     }  
            17. }  
            18. </span>  
            c.關閉功能
            關閉某個功能,也就是刪除某個功能的framework,然后更改功能列表的狀態;
            1. <span style="font-size:18px;">#pragma mark - 關閉某個功能  
            2. - (void)delectFunctionZFJWithDict:(NSMutableDictionary *)dict{  
            3.     NSFileManager *fileMgr = [NSFileManager defaultManager];  
            4.     NSString *savedPath = [NSHomeDirectory() stringByAppendingString:[NSString stringWithFormat:@"/Documents/FunctionZFJ%@",dict[@"mid"]]];  
            5.     BOOL bRet = [fileMgr fileExistsAtPath:savedPath];  
            6.     if (bRet) {  
            7.         NSError *err;  
            8.         //關閉某個功能 就是刪除本地的framework  然后修改本地功能狀態  
            9.         BOOL isScu = [fileMgr removeItemAtPath:savedPath error:&err];  
            10.         if(isScu){  
            11.             [dict setValue:@"0" forKey:@"isopen"];  
            12.             [self updataBaseWithDict:dict];  
            13.         }else{  
            14.             NSLog(@"關閉失敗");  
            15.         }  
            16.     }else{  
            17.         NSLog(@"關閉失敗");  
            18.     }  
            19. }  
            20. </span>  
             
            d.效果圖

            四.源代碼

            在這里面有,兩個framework的源代碼,可項目的代碼;
            注意,如果有多個功能的framework,記住多個framework的命名在同一個功能里面不能重復,不然調取失敗;
             

            五.效果圖

            posted on 2016-11-29 12:37 冬瓜 閱讀(541) 評論(0)  編輯 收藏 引用 所屬分類: 轉貼
            国产午夜福利精品久久2021 | 一本色综合久久| 内射无码专区久久亚洲| 伊人精品久久久久7777| 久久精品国产色蜜蜜麻豆| 97久久国产亚洲精品超碰热| 伊人久久精品线影院| 久久无码中文字幕东京热| 久久99热只有频精品8| 国产精品激情综合久久| 久久国产色av免费看| 久久精品国产影库免费看| 性做久久久久久久久久久| 国产成人综合久久综合| 一本大道久久东京热无码AV| 国产亚洲欧美成人久久片| 久久青青草视频| 精品久久久久久国产三级| 一本色道久久综合狠狠躁| 久久99国产一区二区三区| 久久精品国产清高在天天线| 亚洲&#228;v永久无码精品天堂久久 | 国产情侣久久久久aⅴ免费| 国产精品日韩欧美久久综合| 久久久久久久波多野结衣高潮| 99国内精品久久久久久久| 久久精品国产清高在天天线| 伊人情人综合成人久久网小说 | 亚洲午夜久久久久妓女影院| 久久国产视屏| 国产精品综合久久第一页| 精品精品国产自在久久高清 | 超级碰碰碰碰97久久久久| 久久久久九九精品影院| 国产亚洲色婷婷久久99精品91| 久久精品成人国产午夜| 99精品国产在热久久无毒不卡| 亚洲精品乱码久久久久久自慰| 国产精品中文久久久久久久| 精品久久人人妻人人做精品| 国产精品免费久久久久影院|