标签归档:ios10

2016年12月31日后,NSAllowsArbitraryLoads将被禁用,建议所有iOS App的Web API都升级为HTTPS

苹果的iOS 10正式版本马上就要发布了,而自iOS 10开始,苹果对于网络安全将更加重视,2016年12月31日以后,你将不能用NSAllowsArbitraryLoads来禁止App Transport Security了。

简单说,苹果坚持,你的所有的Web API请求都必须使用https,而如果你需要使用WebView加载外部的网页,考虑到你无法控制外部的网站,苹果引入了新的NSAllowsArbitraryLoadsInWebContent,允许WebView可以加载任意的网页。

The new NSAllowsArbitraryLoadsInWebContent key for your Info.plist file gives you a convenient way to allow arbitrary web page loads to work while retaining ATS protections for the rest of your app.

如果你需要在App中加载任意的网页,那么,你可以在Info.plist中添加NSAllowsArbitraryLoadsInWebContent,这样,你可以加载非安全的http页面,同时保证你的app的其他方面仍然受到App Transport Security的保护。

对于许多公司来说,API团队近期有一项非常重要的工作,也就是,如果你们的Web API仍然是通过明文的http进行调用的,那么,你们需要尽快将API的endpoint升级为https。

如果大家真的来不及升级到https,那怎么办呢。我突然想到,苹果只是禁止了NSAllowsArbitraryLoads,但是我们还是可以NSExceptionDomains,将API对应的域名添加到例外列表中的。

The following listing represents the overall structure of the NSAppTransportSecurity dictionary, showing all possible keys, all of which are optional. Keep this structure in mind as you configure each element of the dictionary, as needed, for your app:
以下代码是NSAppTransportSecurity字典的结构模型。该模型列举了所有可能的键值对,这些键值对都是非必须的。您可以根据这个结构中所示的键值对的信息来编辑Info.plist中的NSAppTransportSecurity字典。

NSAppTransportSecurity : Dictionary {
    NSAllowsArbitraryLoads : Boolean
    NSAllowsArbitraryLoadsInMedia : Boolean
    NSAllowsArbitraryLoadsInWebContent : Boolean
    NSAllowsLocalNetworking : Boolean
    NSExceptionDomains : Dictionary {
         : Dictionary {
            NSIncludesSubdomains : Boolean
            NSExceptionAllowsInsecureHTTPLoads : Boolean
            NSExceptionMinimumTLSVersion : String
            NSExceptionRequiresForwardSecrecy : Boolean   // Default value is YES
            NSRequiresCertificateTransparency : Boolean
        }
    }
}

解决一个WKWebView在iOS 10上的Crash: Invalid parameter not satisfying: targetNode

近日,我遇到了一个让我感到匪夷所思的问题。App使用了WKWebView展示内容,然而,一旦iOS 10的用户手指触摸了WKWebView,app就会立即崩溃,而iOS 9的用户就不会遇到这个问题。

经过调试,我发现Stack Trace和Exception如下


Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid parameter not satisfying: targetNode'
*** First throw call stack:
(0x1864041c0 0x184e3c55c 0x186404094 0x186e8d82c 0x18cc98e4c 0x18c6f551c 0x18c78f364 0x18c20ec70 0x18c791b1c 0x18c791a78 0x18c790d34 0x18c20d34c 0x18c1ddf84 0x18c9b3008 0x18c9aca70 0x1863b2278 0x1863b1bc0 0x1863af7c0 0x1862de048 0x187d5f198 0x18c248bd0 0x18c243908 0x1000e58a0 0x1852c05b8)
libc++abi.dylib: terminating with uncaught exception of type NSException

而调试信息显示问题出现在UIGestureGraphEdge.m的第25行。

Assertion failure in -[UIGestureGraphEdge initWithLabel:sourceNode:targetNode:directed:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3599.6/Source/GestureGraph/UIGestureGraphEdge.m:25

这个文件是Apple的UIKit的一部分啊,难道这是Apple iOS 10的bug?

不管是不是iOS的系统的bug,我想还是找到一个解决方案或者说workaround的好。

最后发现,我原来在app启动的时候,在+(void)load方法中先创建好WKWebView,等到viewDidLoad的时候直接将WKWebView通过addSubView添加到View Controller的view上,这样就可以在viewDidLoad方法中节约了创建WKWebView的时间,可是这样子创建好的WKWebView,在iOS 10上,用户一旦进行了触摸操作,就会出现前面提到的崩溃。

如果我将创建WKWebView的时机稍微延后一些时间,如在load方法中,通过dispatch_after延迟1到2秒再创建WKWebView,那么,WKWebView就可以正常处理用户的触摸操作,不会崩溃。

static NSMutableArray *webViews;
#define WKWebView_Cache_Create_Delay 2
+ (void)load{
    if(SYS_VERSION_LESS(9))return;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        NSUInteger createDelay = 0;
        if(SYS_VERSION_GREATER_OR_EQUAL(10)){
            createDelay = WKWebView_Cache_Create_Delay;
        }
        dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(createDelay * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
            webViews = [[NSMutableArray alloc] init];
            [webViews addObject:[self createWKWebView]];
            [webViews addObject:[self createWKWebView]];
        });
        
    });

此外,在https://forums.developer.apple.com/thread/61432上,也有人遇到了只在iOS 10上才出现的Crash,而Crash的代码的位置也是UIGestureGraphEdge.m的第25行。


flykk
Aug 28, 2016 11:54 PM
When I clicked the NavigationBar in my App,it crashed.It only crashes in iOS 10 .The console log is:
Assertion failure in -[UIGestureGraphEdge initWithLabel:sourceNode:targetNode:directed:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3599.6/Source/GestureGraph/UIGestureGraphEdge.m:25

翻译如下
当我点击我的app的NavigationBar的时候,它就崩溃了。这仅仅发生在iOS 10上。控制台的日志是
Assertion failure in -[UIGestureGraphEdge initWithLabel:sourceNode:targetNode:directed:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit/UIKit-3599.6/Source/GestureGraph/UIGestureGraphEdge.m:25

说实话,这个现象我没到过,但是,崩溃相关的文件和行数确是一样的。期待这位朋友找到解决方法。