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 using UIWebKit for iOS 7 but WKWebKit 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 on General, scroll down to Linked Frameworks and Libraries, and add WebKit.framework as Optional. (I also did it for UIKit.framework) See screenshot:

As for my WebViewController class. It still imports UIKit and WebKit. but the viewDidLoad() sets the view based on kkoltzau's example. Then whenever I need to load/reload the web page, it checks for existence of wkWebView.
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
}
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With