阅读 366

iOS小技能:快速创建OEM项目app(详细版)

引言

贴牌生产(英语:Original Equipment Manufacturer, OEM)

因采购方可提供品牌和授权,允许制造方生产贴有该品牌的产品,所以俗称“贴牌生产”。

需求背景: SAAS平台级应用系统为一个特大商户,提供专属OEM项目,在原有通用app的基础上进行定制化开发。

例如去掉开屏广告,删除部分模块,保留核心模块。更换专属app icon以及主题色。

I 快速创建OEM项目app

1.1  上架资料

  1. 用户协议及隐私政策

  2. App版本、 审核测试账号信息

  3. icon、名称、套装 ID(bundle identifier)

  4. 关键词:

  5. app描述:

  6. 技术支持网址使用:

kunnan.blog.csdn.net/article/det…

1.2  开发小细节

  1. 更换基础配置信息,比如消息推送证书、第三方SDK的ApiKey、启动图、用户协议及隐私政策。

  2. 接口修改:比如登录接口新增SysId请求字段用于区分新旧版、修改域名(备案信息)

  3. 废弃开屏广告pod 'GDTMobSDK' ,'4.13.26'

  4. 修改主题色、按压色(选中状态颜色)、设置SVProgressHUD 样式

  5. 更换启动图、app icon、tabbar icon 、全局搜索替换app名称

  6. 更新日志URL

II、更换第三方SDK的ApiKey

2.1  更换高德定位SDK的apiKey

    NSString *AMapKey = @"";     [AMapServices sharedServices].apiKey = AMapKey; 复制代码

2.2 更新消息推送证书和极光的appKey

  1. Mac 上的“钥匙串访问”创建证书签名请求 (CSR)

a. 启动位于 /Applications/Utilities 中的“钥匙串访问”。

b. 选取“钥匙串访问”>“证书助理”>“从证书颁发机构请求证书”。

c. 在“证书助理”对话框中,在“用户电子邮件地址”栏位中输入电子邮件地址。

d. 在“常用名称”栏位中,输入密钥的名称 (例如,Gita Kumar Dev Key)。

e. 将“CA 电子邮件地址”栏位留空。

f. 选取“存储到磁盘”,然后点按“继续”。

help.apple.com/developer-a…

在这里插入图片描述

  1. 从developer.apple.com 后台找到对应的Identifiers创建消息推送证书,并双击aps.cer安装到本地Mac,然后从钥匙串导出P12的正式上传到极光后台。

docs.jiguang.cn//jpush/clie…在这里插入图片描述

  1. 更换appKey(极光平台应用的唯一标识)

        [JPUSHService setupWithOption:launchOptions appKey:@""                               channel:@"App Store"                      apsForProduction:YES                 advertisingIdentifier:nil]; 复制代码

www.jiguang.cn/accounts/lo…

2.3 更换Bugly的APPId

    [Bugly startWithAppId:@""];//异常上报 复制代码

III 设置主题样式

修改主题色、按压色、设置SVProgressHUD 样式

  1. 改变UITextField中光标颜色

     [[UITextView appearance] setTintColor:ktabSelectedTextColor];     [[UITextField appearance] setTintColor:ktabSelectedTextColor]; 复制代码

  1. 渐变色(修改主题色、按压色)

    <color name="ColorGradientStart">#18ae66</color>     <color name="ColorGradientEnd">#0b9854</color> 复制代码

typedef NS_ENUM(NSUInteger, GradientType) {     GradientTypeTopToBottom = 0,//从上到小     GradientTypeLeftToRight = 1,//从左到右     GradientTypeUpleftToLowright = 2,//左上到右下     GradientTypeUprightToLowleft = 3,//右上到左下 }; + (UIImage*)getMaingradientColorImage{               CGSize size = CGSizeMake(SCREENW, 83.0f);          UIColor *topleftColor =  BASE_start_COLOR;          UIColor *bottomrightColor = BASE_end_COLOR;          UIImage *bgImg = [UIImage gradientColorImageFromColors:@[topleftColor, bottomrightColor] gradientType:GradientTypeLeftToRight imgSize:size];          return bgImg; } + (instancetype)gradientColorImageFromColors:(NSArray*)colors gradientType:(GradientType)gradientType imgSize:(CGSize)imgSize {     NSMutableArray *ar = [NSMutableArray array];     for(UIColor *c in colors) {         [ar addObject:(id)c.CGColor];     }     UIGraphicsBeginImageContextWithOptions(imgSize, YES, 1);     CGContextRef context = UIGraphicsGetCurrentContext();     CGContextSaveGState(context);     CGColorSpaceRef colorSpace = CGColorGetColorSpace([[colors lastObject] CGColor]);     CGGradientRef gradient = CGGradientCreateWithColors(colorSpace, (CFArrayRef)ar, NULL);     CGPoint start;     CGPoint end;     switch (gradientType) {         case GradientTypeTopToBottom:             start = CGPointMake(0.0, 0.0);             end = CGPointMake(0.0, imgSize.height);             break;         case GradientTypeLeftToRight:             start = CGPointMake(0.0, 0.0);             end = CGPointMake(imgSize.width, 0.0);             break;         case GradientTypeUpleftToLowright:             start = CGPointMake(0.0, 0.0);             end = CGPointMake(imgSize.width, imgSize.height);             break;         case GradientTypeUprightToLowleft:             start = CGPointMake(imgSize.width, 0.0);             end = CGPointMake(0.0, imgSize.height);             break;         default:             break;     }     CGContextDrawLinearGradient(context, gradient, start, end, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);     UIImage *image = UIGraphicsGetImageFromCurrentImageContext();     CGGradientRelease(gradient);     CGContextRestoreGState(context);     CGColorSpaceRelease(colorSpace);     UIGraphicsEndImageContext();     return image; } 复制代码

  1. 加载视图样式(设置SVProgressHUD 样式)

- (void)setupSVProgressHUD{          [SVProgressHUD setDefaultStyle:SVProgressHUDStyleLight];//背景块是黑色,字跟圆圈是白色 //SVProgressHUDStyleDark,     [SVProgressHUD setDefaultStyle:SVProgressHUDStyleCustom];//若要自定义必须先设setDefaultStyle为SVProgressHUDStyleCustom,再进行setForegroundColor,setBackgroundColor的配置.     [SVProgressHUD setBackgroundColor: [UIColor colorWithRed:0.0 green:0.0 blue:0.0 alpha:0.10]];     //    [SVProgressHUD setBackgroundLayerColor: UIColor.redColor];          [SVProgressHUD setForegroundColor: UIColor.whiteColor];     [SVProgressHUD setMinimumDismissTimeInterval:0.4];// 设置最小显示时常          [SVProgressHUD setMaximumDismissTimeInterval:0.5];//      } 复制代码

IV 更换基础配置信息

4.1 app启动的新版本提示

更换appid

    [self checkTheVersionWithappid:@""]; 复制代码

检查版本

在这里插入图片描述

 - (void)checkTheVersionWithappid:(NSString*)appid{     [QCTNetworkHelper getWithUrl:[NSString stringWithFormat:@"http://itunes.apple.com/cn/lookup?id=%@",appid] params:nil successBlock:^(NSDictionary *result) {         if ([[result objectForKey:@"results"] isKindOfClass:[NSArray class]]) {             NSArray *tempArr = [result objectForKey:@"results"];             if (tempArr.count) {                                                   NSString *versionStr =[[tempArr objectAtIndex:0] valueForKey:@"version"];                 NSString *appStoreVersion = [versionStr stringByReplacingOccurrencesOfString:@"." withString:@""] ;                 if (appStoreVersion.length==2) {                     appStoreVersion  = [appStoreVersion stringByAppendingString:@"0"];                 }else if (appStoreVersion.length==1){                     appStoreVersion  = [appStoreVersion stringByAppendingString:@"00"];                 }                 NSDictionary *infoDic=[[NSBundle mainBundle] infoDictionary];                 NSString* currentVersion = [[infoDic valueForKey:@"CFBundleShortVersionString"] stringByReplacingOccurrencesOfString:@"." withString:@""];                                  currentVersion = [currentVersion stringByReplacingOccurrencesOfString:@"." withString:@""];                 if (currentVersion.length==2) {                     currentVersion  = [currentVersion stringByAppendingString:@"0"];                 }else if (currentVersion.length==1){                     currentVersion  = [currentVersion stringByAppendingString:@"00"];                 }                 NSLog(@"currentVersion: %@",currentVersion);                                                   if([self compareVesionWithServerVersion:versionStr]){                                                           UIAlertController *alertController = [UIAlertController alertControllerWithTitle:[NSString stringWithFormat:@"%@%@",QCTLocal(@"Discover_a_new_version"),versionStr] message:QCTLocal(@"Whethertoupdate") preferredStyle:UIAlertControllerStyleAlert];                     //                "Illtalkaboutitlater"= "稍后再说";                     //                "Update now" = "立即去更新";                     //                "Unupdate"= "取消更新";                     [alertController addAction:[UIAlertAction actionWithTitle:QCTLocal(@"Illtalkaboutitlater") style:UIAlertActionStyleCancel handler:^(UIAlertAction * _Nonnull action) {                         NSLog(@"取消更新");                     }]];                     [alertController addAction:[UIAlertAction actionWithTitle:QCTLocal(@"Updatenow") style:UIAlertActionStyleDefault handler:^(UIAlertAction * _Nonnull action) {                         NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"itms-apps://itunes.apple.com/app/id%@",appid]];                         if (@available(iOS 10.0, *)) {                             [[UIApplication sharedApplication] openURL:url options:@{} completionHandler:^(BOOL success) {                             }];                         } else {                             // Fallback on earlier vesions                             [[UIApplication sharedApplication] openURL:url];                         }                     }]];                     [[QCT_Common getCurrentVC] presentViewController:alertController animated:YES completion:nil];                 }             }         }     } failureBlock:^(NSError *error) {         NSLog(@"检查版本错误: %@",error);     }]; } 复制代码

4.2  动态获取app名称

获取app名称

                        NSDictionary *mainInfoDictionary = [[NSBundle mainBundle] infoDictionary];                         NSString *appName = [mainInfoDictionary objectForKey:@"CFBundleDisplayName"]; 复制代码

网络权限受限(操作指引)

// 是否开启网络权限 + (BOOL)isNetworkPermissionsOpenWithisShowAlert:(BOOL)showAlert{                  __block BOOL isOpen = YES;                      switch ([ProjectMethod shareProjectMethod].cellularData.restrictedState) {                 case kCTCellularDataRestricted:                     // 网络权限受限,操作指引                     if (showAlert) {                                                  NSDictionary *mainInfoDictionary = [[NSBundle mainBundle] infoDictionary];                         NSString *appName = [mainInfoDictionary objectForKey:@"CFBundleDisplayName"];                         NSString* showAlertcontent = FMSTR(@"请在iPhone的\"设置-%@-无线数据\"中允许WLAN与蜂窝移动网。",appName);                                                                                                                                                                                                   [LBAlertController showAlertTitle:@"无法访问网络" content:showAlertcontent cancelString:@"取消" cancleBlock:nil sureString:@"去设置" sureBlock:^{                                                          // 需要在info.plist中添加 URL types 并设置一项URL Schemes为prefs  IOS10 以后不起作用                             if([[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]]){                                 [[UIApplication sharedApplication] openURL:[NSURL URLWithString:UIApplicationOpenSettingsURLString]];                             }                         } currentController:[QCT_Common getCurrentVC]];                     }                     isOpen = NO;                     break;                 case kCTCellularDataRestrictedStateUnknown:                     // app网络权限不确定                     isOpen = NO;                     break;                 case kCTCellularDataNotRestricted:                     // app网络权限不受限                     //  正常                     isOpen = YES;                     break;                 default:                     break;             } //        };         return isOpen;                    } 复制代码

see also

更多内容请关注 #小程序:iOS逆向,只为你呈现有价值的信息,专注于移动端技术研究领域;更多服务和咨询请关注#公众号:iOS逆向。

 伪原创工具 SEO网站优化  https://www.237it.com/ 

作者:公众号iOS逆向
链接:https://juejin.cn/post/7036299682124922910

文章分类
IOS
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐