前阵子适配 iOS13 的时候遇到一个关于WKWebView设置UserAgent的问题,在iPadOS上,WKWebView的UserAgent变成了类似这样:
Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15) AppleWebKit/605.1.15 (KHTML, like Gecko)
这就导致前端根据UserAgent判断设备的地方出了问题,当时发现其主要原因是iPadOS在设置-Safari浏览器-请求桌面网站的设置默认是开启的,只要把它关掉就正常了,但是你又不能要求审核人员或者用户自己去把它关了,所以当时临时采取了一些其他方法去适配,也参考了如下:
https://forums.developer.apple.com/thread/122189
https://stackoverflow.com/questions/58490952/how-to-test-ios-in-use-from-the-javascript-inside-a-wkwebview-on-ipados-13
等等...其他的实在不记得地址了。
但是忙完那段时间之后,想想之前的处理方案并不靠谱,因为苹果爸爸虽然有不靠谱的地方,但也不至于这样,所以去查阅了一下WKWebView中新增的api,发现果然有个新的api叫做WKWebpagePreferences:
/*! @abstract The set of default webpage preferences to use when loading and rendering content.
@discussion These default webpage preferences are additionally passed to the navigation delegate
in -webView:decidePolicyForNavigationAction:preferences:decisionHandler:.
*/
@property (null_resettable, nonatomic, copy) WKWebpagePreferences *defaultWebpagePreferences API_AVAILABLE(macos(10.15), ios(13.0));
/*! @enum WKContentMode
@abstract A content mode represents the type of content to load, as well as
additional layout and rendering adaptations that are applied as a result of
loading the content
@constant WKContentModeRecommended The recommended content mode for the current platform
@constant WKContentModeMobile Represents content targeting mobile browsers
@constant WKContentModeDesktop Represents content targeting desktop browsers
@discussion WKContentModeRecommended behaves like WKContentModeMobile on iPhone and iPad mini
and WKContentModeDesktop on other iPad models as well as Mac.
*/
typedef NS_ENUM(NSInteger, WKContentMode) {
WKContentModeRecommended,
WKContentModeMobile,
WKContentModeDesktop
} API_AVAILABLE(ios(13.0));
/*! A WKWebpagePreferences object is a collection of properties that
determine the preferences to use when loading and rendering a page.
@discussion Contains properties used to determine webpage preferences.
*/
WK_EXTERN API_AVAILABLE(macos(10.15), ios(13.0))
@interface WKWebpagePreferences : NSObject
/*! @abstract A WKContentMode indicating the content mode to prefer
when loading and rendering a webpage.
@discussion The default value is WKContentModeRecommended. The stated
preference is ignored on subframe navigation
*/
@property (nonatomic) WKContentMode preferredContentMode API_AVAILABLE(ios(13.0));
@end
仔细看完确定这就是我要找的东西。
WKContentModeRecommended behaves like WKContentModeMobile on iPhone and iPad mini
and WKContentModeDesktop on other iPad models as well as Mac.
我们只需要在初始化的时候这么设置,就可以设置WKWebpagePreferences的preferredContentMode为WKContentModeMobile,这样iPadOS上的UserAgent就正常了:
WKWebViewConfiguration *configuration = [[WKWebViewConfiguration alloc] init];
if (@available(iOS 13.0, *)) {
configuration.defaultWebpagePreferences.preferredContentMode = WKContentModeMobile;
}
此外还有和WKWebpagePreferences相关的新api,我们可以按需决定是否实现:
/*! @abstract Decides whether to allow or cancel a navigation.
@param webView The web view invoking the delegate method.
@param navigationAction Descriptive information about the action
triggering the navigation request.
@param preferences The default set of webpage preferences. This may be
changed by setting defaultWebpagePreferences on WKWebViewConfiguration.
@param decisionHandler The policy decision handler to call to allow or cancel
the navigation. The arguments are one of the constants of the enumerated type
WKNavigationActionPolicy, as well as an instance of WKWebpagePreferences.
@discussion If you implement this method,
-webView:decidePolicyForNavigationAction:decisionHandler: will not be called.
*/
- (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction preferences:(WKWebpagePreferences *)preferences decisionHandler:(void (^)(WKNavigationActionPolicy, WKWebpagePreferences *))decisionHandler API_AVAILABLE(macos(10.15), ios(13.0));
在完成适配之后我也查了一下网上的资料,发现很多文章并没有深究,还是之前那些奇奇怪怪的方案,也可能大佬们懒得总结吧,所以这里分享一下我的解决方案(还是要好好看看api的更新)。