Xcode 6 + iOS 8 SDK but deploy on iOS 7 (UIWebKit & WKWebKit)
Solution 1
You will need to check if WKWebView is available, and fall back to UIWebView if its not.
Make sure you weak link WebKit.framework (set to optional)
Objective-C:
WKWebView *wkWebView = nil;
UIWebView *uiWebView = nil;
Class wkWebViewClass = NSClassFromString(@"WKWebView");
if(wkWebViewClass) {
WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init];
// ...
wkWebView = [[wkWebViewClass alloc] initWithFrame:frame configuration:config];
[self.view addSubview:wkWebView];
}
else {
uiWebView = [[UIWebView alloc] initWithFrame:frame];
[self.view addSubview:uiWebView];
}
Swift:
var wkWebView : WKWebView?
var uiWebView : UIWebView?
if NSClassFromString("WKWebView") {
let config = WKWebViewConfiguration()
// ...
wkWebView = WKWebView(frame: frame, configuration: config)
self.view.addSubview(wkWebView)
}
else {
uiWebView = UIWebView(frame: frame)
self.view.addSubview(uiWebView)
}
Then elsewhere in your code:
Objective-C:
if(wkWebView) {
// WKWebView specific code
}
else {
// UIWebView specific code
}
Swift:
if let w=wkWebView {
// WKWebView specific code
}
else if let w=uiWebView {
// UIWebView specific code
}
Solution 2
If you need to support iOS7, you cannot use WebKit2 (WK*
) classes, or you need to implement twice the logic, once for iOS8 using WK*
and once using UIWeb*
, and at runtime choose according to the operating system version.
Related videos on Youtube
netwire
Updated on September 15, 2022Comments
-
netwire over 1 year
We are creating an app using Xcode 6 beta 5 + Swift on iOS 8 SDK. We'd like to deploy to iOS 7 as well. Is that possible? When we set the deployment target of the project to 7.0, we get compile time errors like this:
Undefined symbols for architecture x86_64: "_OBJC_CLASS_$_WKPreferences", referenced from: __TMaCSo13WKPreferences in WebViewController.o "_OBJC_CLASS_$_WKWebView", referenced from: __TMaCSo9WKWebView in WebViewController.o "_OBJC_CLASS_$_WKWebViewConfiguration", referenced from: __TMaCSo22WKWebViewConfiguration in WebViewController.o ld: symbol(s) not found for architecture x86_64 clang: error: linker command failed with exit code 1 (use -v to see invocation)
I believe that's because we are using
WKWebKit
, which is supported by iOS 8+ only. We are ok with usingUIWebKit
for iOS 7 butWKWebKit
for iOS 8. How do we define that?Our class definition looks like this...
import WebKit class WebViewController: UIViewController, WKNavigationDelegate { ... }
and it's called by:
let mainStoryboard = UIStoryboard(name: "Main", bundle: nil) let destinationVC = mainStoryboard.instantiateViewControllerWithIdentifier("WebViewController") as WebViewController presentViewController(destinationVC, animated: true, completion: nil)
I was thinking about using this fragment to call
presentViewController
but that doesn't solve the compile time issues. (NSFoundationVersionNumber
doesn't solve compile time issues either)if ((UIDevice.currentDevice().systemVersion as NSString).floatValue >= 8.0) { } else { }
UPDATE: kkoltzau has the correct answer. I'm adding some more info for others.
First, go to your
Project
, click onGeneral
, scroll down toLinked Frameworks and Libraries
, and addWebKit.framework
as Optional. (I also did it forUIKit.framework
) See screenshot:As for my
WebViewController
class. It still importsUIKit
andWebKit
. but theviewDidLoad()
sets the view based on kkoltzau's example. Then whenever I need to load/reload the web page, it checks for existence ofwkWebView
. -
rmaddy over 9 yearsNone of this addresses the question which is about linker errors.
-
netwire over 9 yearsThanks kkoltzau, let me try and report back. Interesting to know you can set class via 'NSClassFromString'
-
kevin over 9 years@rmaddy Weak linking to WebKit.framework, mentioned in the second sentence, covers the linker error.
-
netwire over 9 yearsThanks kkoltzau about setting WebKit.framework to optional. I can't paste screenshot, but I'll do so as an answer for others.
-
netwire over 9 yearsMy class also implements
WKNavigationDelegate
, including methods such as ` func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation)` andfunc webView(webView: WKWebView, didCommitNavigation navigation: WKNavigation)
. How do I include them in this example? -
netwire over 9 yearsThe app was able to compile, but at runtime, on an iOS 8 device, it's giving me an error that
wkWebView = WKWebView(frame: webViewWrapper.bounds, configuration: configuration)
resulted in nil, as no WKWebView was created. I can't tell if it's becauselet configuration = WKWebViewConfiguration()
failed or not. -
kevin over 9 years@Dean Regarding WKNavigationDelegate, just implement it as usual. I don't know why WKWebView would fail to create assuming WebKit.framework is properly linked.
-
ABeanSits over 9 years@kkoltzau I understand why you would instantiate the WKWebView class from a string, but what is the reason for doing it with the WKWebViewConfiguration class as well?
-
Piwaf almost 9 yearsThat sentence 2 about "Make sure you weak link WebKit.framework (set to optional)" is super important. I actually didn't even have WebKit.Framework listed so I needed to added it and set to Optional.