《iOS开发进阶》观后-下篇(注意问题篇)

简介

  • 本篇主要内容是实际开发中的思考总结,分别从安全性、UIWebview/WKWebview、脚本处理、内购、动态字库、其他等方面说,其中其他部分设备比较广,但实际使用相对较小或较基础。还会说说对APP持续化概念。

前言

  • 由于篇幅问题,会分三篇描述对应不同内容。辅助工具,底层原理,开发中要注意问题三个方面,谈谈对应的总结。本人觉得书只是一个索引,特别对于技术类书籍,基本都是通过书籍引入一些观点,然后在通过其它第三方途径进行扩展。所以本文描述内容不一定就是书本内容,会与自身实践经验,还有部分内容精简和拓展。有些基础概念第三方描述已足够详细,实例也足够详细,本文仅仅提出一些个人总结理解,不在重复描述具体功能原理。

  • 文字不如图片直观,所以先上一张本系列描述的观点的思维导图,梳理脉络。红色部分为本文内容梳理。

  • 《思维导图链接(点我打开)最新版本》

输入图片说明

安全性

1 网络安全性

  • https 通信协议的加密 《HTTPS连接过程及证书自定义认证》 这篇是之前做ssl加密认证总结的。

  • URL加密,主要针对get/put/del.后端交互可以用aes,h5可以用base64.

  • 内容加密,主要针对post.json采用AES加密,app与后端同用一套加密发送前加密,到后端解密。返回过程也是。

  • 出于安全性,我是觉得用post代替所有协议更加好,但是效率上post会比get低。《post和get 请求区别+原理》

2 本地安全性

  • 《iOS本地数据存储安全》 《iOS Keychain理解》

  • 还有各种第三库TMDiskCache,FDMB,YYCache,这些都是基于文件的所以当沙盒被破时加密性会大大下降。

  • 而Keychain适合存需要加密的信息,如金钱的,账号的,积分的等等。。。。

    扫描二维码关注公众号,回复: 692211 查看本文章

UIWebview/WKWebview (这里主要是UIWebview)

1 JS语言特性

  • 解释性脚本语言,javascript不需要编译,只需要嵌入到html代码中,由浏览器逐行加载解释执行。

  • javascript是一种基于对象的语言,使用已经创建好的对象来,和面向对象的先锋需设计语言不同,javascript并不支持继承和重载。

  • 语言简单,弱类型,语法和java,C语言类似,变量不需要声明和指定类型即可使用,是一种弱类型语言。

  • 最重要的特点就是只有2点单线程,并且都是异步处理的。

2 同步异步/UI线程阻塞

  • UIWebview的stringByEvaluatingJavaScriptFromString是一个同步方法,会等待js方法执行完成,耗时操作建议利用js异步特点,全部使用setTimeout的function中,以加快回调结束。
//oc

NSString *jsStr = [NSString stringWithFormat:@"setLocation('%@')",@"广东省深圳市南山区学府路XXXX号"];
[self.webView stringByEvaluatingJavaScriptFromString:jsStr];


//js
function setLocation(location) {
    asyncAlert(location);
    document.getElementById("returnValue").value = location;
}

function asyncAlert(content) {
    setTimeout(function(){
               alert(content);
               },1);
}

3 混编原理

  • 之前也是用UIWebView + 拦截URL 的方式实现的JS与OC 交互。但是,都会封装一层作为app的调用函数,然后基础基类,然而现在的项目,居然是逐个控制器解析url,再单独处理。我觉得是很不科学的。
// js调用
function loadURL(url) {
    var iFrame;
    iFrame = document.createElement("iframe");
    iFrame.setAttribute("src", url);
    iFrame.setAttribute("style", "display:none;");
    iFrame.setAttribute("height", "0px");
    iFrame.setAttribute("width", "0px");
    iFrame.setAttribute("frameborder", "0");
    document.body.appendChild(iFrame);
    // 发起请求后这个iFrame就没用了,所以把它从dom上移除掉
    iFrame.parentNode.removeChild(iFrame);
    iFrame = null;
}

// oc拦截
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    NSURL *URL = request.URL;
    NSString *scheme = [URL scheme];
    if ([scheme isEqualToString:@"haleyaction"]) {
        [self handleCustomAction:URL];
        return NO;
    }
    return YES;
}

4 WKWebview

脚本处理

1 持续化集成

  • 《手把手教你利用Jenkins持续集成iOS项目》 文章中的xcrun好似在xcode8就开始被废弃看。

  • 持续集成指的是,频繁地(一天多次)将代码集成到主干。持续集成的目的,就是让产品可以快速迭代,同时还能保持高质量。它的核心措施是,代码集成到主干之前,必须通过自动化测试。只要有一个测试用例失败,就不能集成。

  • 打包脚本以在上篇xcodebulid简述中提供了。

  • 方法一,jenken部署mac服务器上,理由jenken定时任务定时部署。

  • 方法二,Jenkins跑远程ssh运行打包脚本,然后发布到第三方(蒲公英之类)。

  • 神器fastlane工具,这个以后准备了解一下。

2 动态库分离 参考《自建framework提交审核报错 ERROR ITMS-90087解决办法》

  • 动态库分离,架构文件分离。

  • 增加 Thinned Run Script

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"

# This script loops through the frameworks embedded in the application and
# removes unused architectures.
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
echo "Executable is $FRAMEWORK_EXECUTABLE_PATH"

EXTRACTED_ARCHS=()

for ARCH in $ARCHS
do
echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
done

echo "Merging extracted architectures: ${ARCHS}"
lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
rm "${EXTRACTED_ARCHS[@]}"

echo "Replacing original executable with thinned version"
rm "$FRAMEWORK_EXECUTABLE_PATH"
mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"

done

3 其他

  • 这个就设计到各种其他处理,如图片去重,图片批量压缩等等,也不详细说了。

内购 (简述一些概念,没有具体开发)

1 基本过程

2 校验环境

  • 线上包也是采用沙盒验证的,正式验证服返回21007,在验证一次测试服。

3 安全性

  • 这里主要就是凭证的安全性问题,因为苹果只有验证凭证合法不合法,与用户无关,如果凭证被盗了,就会导致其他人用了这个凭证,导致金钱丢失。所有建议用Keychain。

动态字库 《动态下载系统提供的多种中文字体》

1 实现

// 1 假如我们现在要下载娃娃体字体,它的PostScript名称为DFWaWaSC-W5。具体的步骤如下:
- (BOOL)isFontDownloaded:(NSString *)fontName {   
//判断是否系统支持某种字体
- (BOOL)isFontDownloaded:(NSString *)fontName {
    UIFont* aFont = [UIFont fontWithName:fontName size:12.0];
    if (aFont && ([aFont.fontName compare:fontName] == NSOrderedSame
                  || [aFont.familyName compare:fontName] == NSOrderedSame)) {
        return YES;
    } else {
        return NO;
    }
}

// 3 如果该字体下载过了,则可以直接使用。否则我们需要先准备下载字体API需要的一些参数,如下所示:
  
// 用字体的PostScript名字创建一个Dictionary
NSMutableDictionary *attrs = [NSMutableDictionary dictionaryWithObjectsAndKeys:fontName, kCTFontNameAttribute, nil];

// 创建一个字体描述对象CTFontDescriptorRef
CTFontDescriptorRef desc = CTFontDescriptorCreateWithAttributes((__bridge CFDictionaryRef)attrs);

// 将字体描述对象放到一个NSMutableArray中
NSMutableArray *descs = [NSMutableArray arrayWithCapacity:0];
[descs addObject:(__bridge id)desc];
CFRelease(desc);

// 4 准备好上面的descs变量后,则可以进行字体的下载了,代码如下:
__block BOOL errorDuringDownload =NO;

CTFontDescriptorMatchFontDescriptorsWithProgressHandler( (__bridge CFArrayRef)descs,NULL,  ^(CTFontDescriptorMatchingState state, CFDictionaryRef progressParameter) {
    double progressValue = [[(__bridge NSDictionary *)progressParameter objectForKey:(id)kCTFontDescriptorMatchingPercentage] doubleValue];
    if (state == kCTFontDescriptorMatchingDidBegin) {
        NSLog(@"字体已经匹配");
    } elseif (state == kCTFontDescriptorMatchingDidFinish) {
        if (!errorDuringDownload) {
            NSLog(@"字体%@下载完成", fontName);
        }

    } elseif (state == kCTFontDescriptorMatchingWillBeginDownloading) {
        NSLog(@"字体开始下载");
    } elseif (state == kCTFontDescriptorMatchingDidFinishDownloading) {
        NSLog(@"字体下载完成");
        dispatch_async( dispatch_get_main_queue(), ^ {

            // 可以在这里修改UI控件的字体

        });
    } elseif (state == kCTFontDescriptorMatchingDownloading) {
        NSLog(@"下载进度 %.0f%% ", progressValue);
    } elseif (state == kCTFontDescriptorMatchingDidFailWithError) {
        NSError *error = [(__bridge NSDictionary *)progressParameter objectForKey:(id)kCTFontDescriptorMatchingError];
        if (error !=nil) {
            _errorMessage = [error description];
        } else {
            _errorMessage = @"ERROR MESSAGE IS NOT AVAILABLE!";
        }
        // 设置标志
        errorDuringDownload = YES;
        NSLog(@"下载错误: %@", _errorMessage);
    }  
    return (BOOL)YES;

});

2 利弊

  • 这种下载不是下载到app是二下载到一个系统公共目录(/private/var/mobile/Library/Assets/com_apple_MobileAsset_Font/)所有APP都可以用的。

  • 节省空间,一个字符要10-20M以上。

其他

1 CoreText

  • 这个书中是类比UIwebview,HybridApp是APP趋势,所以个这部分用UIwebview/WKWebview代替就好,所有也没特别细看这部分。

2 UIwindow

3 开发技巧、调试技巧、审核技巧

  • 书中描述的也是比较基础的内容工具使用,基本上几年开发经验都会用到,这里也不细说了。

原文:http://raychow.linkfun.top/2018/01/13/archives/1_ios/2017-section-3/index/

猜你喜欢

转载自my.oschina.net/u/3729367/blog/1606391