WKWebView fallback to UIWebView in swift2? - swift2

In my SWIFT project, I use WKWebView for iOS 8 and fall back to UIWebView for iOS 7, using this line of code:
var webView: WKWebView?
#IBOutlet weak var containerView: UIWebView!
However, this is not allowed in SWIFT 2 in the new Xcode 7. What is the best alternative if I still want to support iOS 7?

I had the same problem. I added this dictionary to my info.plist. Now the WKWebView loads as expected.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>

Here's the example code for just the purpose.
var subWKView: UIView?
//on view load, initiate the WKWebView and fall back to UIWebView
override func loadView() {
if #available(iOS 8.0, *) {
//this is only allowed to be used in the func block
let webView: WKWebView!
webView = WKWebView()
//code for initiating WKWebView using addSubview
//reference to the WKWebView
self.subWKView = webView
} else {
//use UIView
}
}
//Use WKWebView in other func blocks
func useWKWebView() {
if #available(iOS 8.0, *) {
//cast to WKWebView
let webView = self.subWKView as! WKWebView
//use the webView
} else {
//use UIView
}
}

Related

Xcode 11 beta: AppDelegate file doesn't have window global variable

I am facing an issue in Xcode 11 beta.
The problem is that I am not getting default window variable declared in AppDelegate file.
Is anybody facing this same issue?
In Xcode 11 this is now done in SceneDelegate
EDIT: if you’re still supporting iOS 12 or prior (or want to support 13 plus prior)
Add the UIWindowSceneDelegate to ApplicationDelegate
Add : var window:UIWindow?
Then proceed as you would to setting up in didFinishLaunching
The default var window: UIWindow? Is now moved in SceneDelegate.swift. To set a rootViewController in Xcode 11 you can work within SceneDelegate.swift file, In the scene delegate, you must create the window instance and the root view controller like below:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// set or create your viewController here
let yourViewController = UIStoryboard.init(name: "Main", bundle: nil).instantiateViewController(identifier: "yourViewController") as! YourViewController
// set the rootViewController here using window instance
self.window?.rootViewController = yourViewController
}
Also this answer is helpful : Why is manually setup root view controller showing black screen?
Hope it will help you!
My approach:
first, in AppDelegate create a static property with the class of the view controller you want to access, like this
class AppDelegate: UIResponder, UIApplicationDelegate {
// MARK: Home
static var homeViewController: HomeViewController?
...
}
then, in the view controller
// MARK: - Managing the view
override func viewDidLoad() {
super.viewDidLoad()
// Singleton
AppDelegate.homeViewController = self
...
}
how to use:
extension UIViewController {
var homeViewController: HomeViewController? {
if let controller = self as? HomeViewController {
return controller
}
return AppDelegate.homeViewController
}
}
In my case, that's all it takes.
var window: UIWindow? // add this by yourself
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: Device.bounds)
let root = DDTabBarController()
window?.rootViewController = root
window?.makeKeyAndVisible()
return true
}

Cannot change PlivoLoginAppDelegate to swift in iOS SDK

In your iOS SDK PlivoLogin, there are PlivoLoginAppDelegate.h and PlivoLoginAppDelegate.m.
I want to change it to swift file.
I changed it to the following.
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
class var shared: AppDelegate {
return UIApplication.shared.delegate as! AppDelegate
}
var providerDelegate: ProviderDelegate?
var window: UIWindow?
#IBOutlet var viewController: ViewController?
var phone: Phone?
// MARK: UIApplicationDelegate
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
print("Finished launching with options: \(launchOptions)")
// // Phone
self.phone = Phone()
self.viewController = self.window?.rootViewController as? ViewController
self.viewController?.phone = self.phone
self.phone?.setDelegate(self.viewController)
return true
}
...
}
But the log only says
Creating endpoint
Generating random password
and stops, fails to get a delegate response to - (void)successWithResponse:.
How can we get a delegate response?
Plivo Sales Engineer here.
Plivo iOS SDK has Objective C interface and you can access the Objective-C library from the Swift 3.0. This is a sample app in the Swift 3.0 using the iOS SDK's Objective-C interface. This app makes outgoing calls and gets delegate callbacks in Swift 3.0.

Replace NSViewController under Swift2 Storyboard MAC OSX

I am new to Mac OSX and with Apple promoting the fact that the bodies of code are becoming similar decided to tell the folk I am writing code for we should be able to do a Mac OSX version. iPhone and iPad versions are all good and about to release second version so no issues there.
So I am subclassing NSWindowController to get access to the Toolbar and worked out how to remove and add items on the toolbar, but for the life of me I can not get one NSViewController (firstViewController) to dismiss and bring up the second NSViewController (secondViewController) in the same NSWindowController.
So the 2 issues are that
1. I want to be able to performSegueWithIdentifier from the first NSViewController in code and
2. bring up the second NSViewController by replacing the first NSViewController in the same NSWindowController.
If I add a button to the firstViewController and put a segue to the secondViewController then when I select the button the secondViewController comes up just fine but in a seperate window not the same NSWindowController that I want it to and the firstViewController does not get replaced but stays in the NSWindowController.
So I know the segue idea will work but its not working in code and when I do insert the segue from a button it works but into a seperate NSViewController that is not part of the NSWindowController.
I am trying to find some programming guide from Apple on the issue but no luck so far.
Here is an overview from my Storyboard:
Here is my NSWindowController subclassed and the func loginToMe2Team is trigger from the NSToolBar and its working just find as the print statements show up on the console.
import Cocoa
class me2teamWindowsController: NSWindowController {
#IBOutlet var mySignUp : NSToolbarItem!
#IBOutlet var myToolbar : NSToolbar!
let controller = ViewController()
override func windowDidLoad() {
super.windowDidLoad()
print("window loaded")
}
override func windowWillLoad() {
print("window will load")
}
#IBAction func logInToMe2Team(sender: AnyObject){
controller.LogIn() //THIS IS THE FUNC I AM TESTING WITH
}
#IBAction func signUpToMe2Team(sender: AnyObject){
controller.signUp()
}
Here is my NSViewController subclassed with the func LogIn. Its getting selected just fine but the performSegueWithIdentifier is not. And I did cut and past the Identifier to make absolutely sure it was the same.
import Cocoa
import WebKit
class ViewController: NSViewController {
#IBOutlet weak var theWebPage: WebView!
#IBOutlet weak var progressIndicator: NSProgressIndicator!
override func viewDidLoad() {
super.viewDidLoad()
let urlString = "https://thewebpage.com.au"
self.theWebPage.mainFrame.loadRequest(NSURLRequest(URL: NSURL(string: urlString)!))
}
override func viewDidAppear() {
}
func LogIn() {
print("I logged in")
self.performSegueWithIdentifier("goToTeamPage", sender: self)
//THIS IS THE BIT THATS NOT WORKING
}
func signUp() {
print("I have to sign up now")
}
override var representedObject: AnyObject? {
didSet {
}
}
func webView(sender: WebView!, didStartProvisionalLoadForFrame frame: WebFrame!)
{
self.progressIndicator.startAnimation(self)
}
func webView(sender: WebView!, didFinishLoadForFrame frame: WebFrame!)
{
self.progressIndicator.stopAnimation(self)
}
}
You need to use a custom segue class (or possibly NSTabViewController if it’s enough for your needs). Set the segue’s type to Custom, with your class name specified:
…and implement it. With no animation, it’s simple:
class ReplaceSegue: NSStoryboardSegue {
override func perform() {
if let src = self.sourceController as? NSViewController,
let dest = self.destinationController as? NSViewController,
let window = src.view.window {
// this updates the content and adjusts window size
window.contentViewController = dest
}
}
}
In my case, I was using a sheet and wanted to transition to a different sheet with a different size, so I needed to do more:
class ReplaceSheetSegue: NSStoryboardSegue {
override func perform() {
if let src = self.sourceController as? NSViewController,
let dest = self.destinationController as? NSViewController,
let window = src.view.window {
// calculate new frame:
var rect = window.frameRectForContentRect(dest.view.frame)
rect.origin.x += (src.view.frame.width - dest.view.frame.width) / 2
rect.origin.y += src.view.frame.height - dest.view.frame.height
// don’t shrink visible content, prevent minsize from intervening:
window.contentViewController = nil
// animate resizing (TODO: crossover blending):
window.setFrame(window.convertRectToScreen(rect), display: true, animate: true)
// set new controller
window.contentViewController = dest
}
}
}

Detection of WebView load finish

I am creating a simple app with a WebView basing on this tutorial.
I would like to display a progress indicator while loading the page, but the methods didStartProvisionalLoadForFrame and didFinishLoadForFrame are never called. What am I doing wrong?
ViewController.swift
import Cocoa
import WebKit
class ViewController: NSViewController {
#IBOutlet weak var webView: WebView!
#IBOutlet weak var webViewProgressIndicator: NSProgressIndicator!
let messengerUrl = "https://www.messenger.com/"
override func viewDidLoad() {
super.viewDidLoad()
self.webView.mainFrame.loadRequest(NSURLRequest(URL: NSURL(string: messengerUrl)!))
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
func webView(sender: WebView!, didStartProvisionalLoadForFrame frame: WebFrame!)
{
self.webViewProgressIndicator.startAnimation(self)
}
func webView(sender: WebView!, didFinishLoadForFrame frame: WebFrame!)
{
self.webViewProgressIndicator.stopAnimation(self)
}
}
I am using Xcode 7 Beta and OS X 10.11 Beta.
Rich's answer works on Xcode 7.0.1 ElCaptain Swift2
BUT I had to connect it in the connections inspector as Swift2 did not accept
self.view.frameLoadDelegate = self
as it gave the following error
Cannot assign a value of type 'ViewController' to a value of type
'WebFrameLoadDelegate!'
So as long as you connect it up as follows, all works great.
The tutorial missed out something, Need to add:
self.webView.frameLoadDelegate = self
(can be done in connections inspector)
then call the load..
self.webView.mainFrame.loadRequest(NSURLRequest(URL: NSURL(string: messengerUrl)!))
Also add the WebFrameLoadDelegate interface to your ViewController.. (thanks tjv)
class ViewController: NSViewController, WebFrameLoadDelegate{ .....
You need to assign the delegate of your UIWebview ie: webview.delegate = self

How to set a custom user-agent for an osx webview using swift

I'm having trouble setting a custom user-agent for my webview in the demo I am just trying to set it to my Safari user-agent. It is seemingly very difficult to find examples of how to go about doing this in a swift based osx cocoa application.
Here's my code:
import Cocoa
import WebKit
class ViewController: NSViewController {
#IBOutlet weak var webView: WebView!
#IBOutlet weak var progressIndicator: NSProgressIndicator!
override func viewDidAppear() {
super.viewDidAppear()
self.view.window?.titleVisibility = .Hidden
self.view.window?.titlebarAppearsTransparent = true
self.view.window?.styleMask |= NSFullSizeContentViewWindowMask
let urlString = NSURL(string: "http://whatsmyuseragent.com")
NSUserDefaults.standardUserDefaults().registerDefaults(["UserAgent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_4) AppleWebKit/600.7.12 (KHTML, like Gecko) Version/8.0.7 Safari/600.7.12"])
self.webView.mainFrame.loadRequest(NSMutableURLRequest(URL: urlString!))
}
override var representedObject: AnyObject? {
didSet {
// Update the view, if already loaded.
}
}
override func webView(sender: WebView!, didStartProvisionalLoadForFrame frame: WebFrame!) {
self.progressIndicator.startAnimation(self)
}
override func webView(sender: WebView!, didFinishLoadForFrame frame: WebFrame!) {
self.progressIndicator.stopAnimation(self)
}
override func mouseEntered(event: NSEvent) {
}
}
Also I have seen UIWebView iOS5 changing user-agent the code example given seemingly does not do anything and/or I am putting it in the wrong place. I have 2 files "AppDelegate.swift" and "ViewController.swift" I have tried the code at various places in both files to no avail.
Thanks!
The important properties for this are WebView customUserAgent: and WebView applicationNameForUserAgent:.
To replace the entire User-Agent string with a new one:
webView.customUserAgent = "MyAgent/1.0.0"
To append your app string onto the existing user agent string:
webView.applicationNameForUserAgent = "MyAgent/1.0.0"
Further details:
https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/DisplayWebContent/Tasks/Spoofing.html

Resources