0

This answer addresses how to use a Swift class from a framework that may not be linked to an app, but is present in the target OS. Relatedly, but a bit different, I'd like to know how to conditionally use a Swift class that may not be included in the target OS. For example, say I have an app, written in Swift, that targets iOS 7. I want to use WKWebView if I'm on iOS 8, and UIWebView if I'm on iOS 7. This doesn't work:

if NSClassFromString("WKWebView") == nil {
    var wv = WKWebView()
} else {
    var wv = UIWebView()
}

Because my app targets iOS 7, I get a compile-time error:

Undefined symbols for architecture i386:
  "_OBJC_CLASS_$_WKWebView", referenced from:
      __TMaCSo9WKWebView in MyWebKitViewController.o

I tried just assigning the WKWebView to an AnyObject property, but then I can’t call methods on it. So how can I get Swift to just check for these things at runtime?

Community
  • 1
  • 1
theory
  • 9,178
  • 10
  • 59
  • 129
  • What do you mean "my app targets iOS 7"? Your Base SDK is iOS 7? Or your deployment target (minimum iOS version) is iOS 7? – newacct Jan 27 '15 at 22:04
  • Did you remember to link to WebKit as optional? Since the framework might not exist on older OS's? – newacct Jan 27 '15 at 22:06
  • @newacct The latter. – theory Jan 27 '15 at 22:10
  • @newacct Ah-ha. I set the IOS Deployment Target to 7.0, then added the WebKit framework as an optional linked framework, and now it all works! If you wanted to add an answer to this effect, I would gladly accept it. – theory Jan 27 '15 at 22:26
  • I am not sure that that is the right answer though, because in Swift you should be able to `import` a module and not even put it in the project settings at all – newacct Jan 28 '15 at 00:41
  • I'm assuming that auto-linking only works if the requisite classes (or imports) are available for the targeted version of iOS. That would explain it, I think. If I'm explicit in linking it—even as an optional—it seems to work very well. – theory Jan 28 '15 at 00:44
  • It looks like you have a type you need the first `(` after `If` and the one after `nil` or am I mistaken> – Jed Grant May 19 '15 at 22:20
  • Yeah, parens are not required around the conditional expression in an `if` statement in Swift, @JedGrant. – theory May 21 '15 at 06:14

2 Answers2

0

I'm new to Swift so I don't know if this is Swift or not, but I found this on a different question. https://stackoverflow.com/a/25874127/1012144

http://floatlearning.com/2014/12/uiwebview-wkwebview-and-tying-them-together-using-swift/

 if (NSClassFromString("WKWebView") != nil) {
   // Use WebKit
 } else {
   // Fallback on UIWebView
 }
Community
  • 1
  • 1
Jed Grant
  • 1,305
  • 1
  • 17
  • 47
  • If you also set the IOS Deployment Target to 7.0, then yes, this appears to be the correct answer. – theory May 21 '15 at 06:16
0

The code in the OP is nearly correct; it just needed to use != instead of ==:

if NSClassFromString("WKWebView") != nil {
    var wv = WKWebView()
} else {
    var wv = UIWebView()
}

To make it work, be sure to set iOS Deployment Target to 7.0. Otherwise you get the undefined symbol errors.

theory
  • 9,178
  • 10
  • 59
  • 129