My Swift app with UIWebView crashes with exc_bad_access when trying to get current URL. It also crashes only in some cases (often depends on the actions performed by user within that UIWebView). Try loading the url provided in code and then tapping cancel. It never crashes though if I don't implement methods from UIWebViewDelegate protocol.
class AuthViewController: UIViewController, UIWebViewDelegate {
#IBOutlet var authWebView: UIWebView
init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: NSBundle?) {
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
// Custom initialisation
}
override func viewDidLoad() {
super.viewDidLoad()
self.authWebView.delegate = self
var url = NSURL(string:"http://oauth.vk.com/authorize?client_id=4423823&scope=audio&display=mobile&v=5.21")
var urlRequest = NSMutableURLRequest(URL: url)
self.authWebView.loadRequest(urlRequest)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func webViewDidFinishLoad(webView:UIWebView) {
NSLog( webView.request!.URL!.absoluteString )
}
}
I was also trying to implement this method to check if request object exists before getting the URL but it didn't help.
func webView(webView: UIWebView!,
shouldStartLoadWithRequest request: NSURLRequest!,
navigationType navigationType: UIWebViewNavigationType) -> Bool {
if !self.authWebView.request {
return false
} else {
return true
}
}
I've found the error:
Some URL contains special characters, such as %# or # which is used for formatting in NSLog. If any of those characters is used in the string the first argument for NSLog, than more arguments required for formatting.
E.G.
NSLog("http://someurl.com/") // this is fine (no special chars used)
NSLog("http://someurl.com/#somehash?x=%#") // this is not fine (%# is used in URL, NSLog thinks that I'm formatting the string
var someURLString = "http://someurl.com/#somehash?x=%#"
NSLog("%#", someURLString) // this is fine and the way it has to be done
Thanks everyone who took a look at my question!
Related
I am creating one SDK to get the url from user and load. So ai m creating my own class with WKWebview. But i am getting few issues about Instance member 'webView' cannot be used on type 'MyWebView(UIview)'
Code :
import Foundation
import WebKit
public class MyWebView: UIView, WKNavigationDelegate {
// initialize the view
var webView: WKWebView!
// load the view
private func loadView() {
webView = WKWebView()
webView.navigationDelegate = self
}
// get the url and load the page
public static func loadUrl(Url: String) {
MyWebView.webView.load(URLRequest(url: URL(string: Url)!))
}
}
In my loadUrl, what ever user sending i need to use that url and load the url. Same in my view controller will look like :
import UIKit
class ViewController: UIViewController {
var webView: MyWebView!
override func loadView() {
view = webView
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
Any help would be great.
Your loadUrl function should not be static, since it needs access to an instance property, webView. Making the function non-static solves the issue.
Also a couple of minor improvements: don't force unwrap the URL init, since with an incorrect input that will crash. Use optional binding to safely unwrap it instead. I'd also suggest renaming the input argument label on loadUrl, since there's no point in having to right out loadUrl(Url:) every time you call the func, loadUrl( reads more naturally.
public func loadUrl(_ urlString: String) {
guard let url = URL(string: urlString) else { return }
webView.load(URLRequest(url: url))
}
I am trying to get the authentication token to be able to grab a user's info. I registered my app in the instagram api page and everything seems to work except that I am not able to retrieve an authentication token or anything information. (I think it might be because of the redirect url i just made a dummy url) I can login to my instagram account and authorize my app to retrieve information but I dont get anything printed on my console so Im assuming im not being able to retrieve anything.
the code:
import UIKit
import WebKit
class ViewController3: UIViewController, UIWebViewDelegate {
#IBOutlet weak var WebView1: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let authURL = String(format: "%#?client_id=%#&redirect_uri=%#&response_type=token&scope=%#&DEBUG=True", arguments: [API.INSTAGRAM_AUTHURL,API.INSTAGRAM_CLIENT_ID,API.INSTAGRAM_REDIRECT_URI, API.INSTAGRAM_SCOPE])
let urlRequest = URLRequest.init(url: URL.init(string: authURL)!)
WebView1.load(urlRequest)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
var tts = segue.destination as! Manage_Ad_VC
tts.S_Media_R = "Instagram"
}
func WebView1(_ WebView1: UIWebView, shouldStartLoadWith request:URLRequest, navigationType: UIWebViewNavigationType) -> Bool{
return checkRequestForCallbackURL(request: request)
}
func checkRequestForCallbackURL(request: URLRequest) -> Bool {
print("Instagram authentication token ==")
let requestURLString = (request.url?.absoluteString)! as String
if requestURLString.hasPrefix(API.INSTAGRAM_REDIRECT_URI) {
let range: Range<String.Index> = requestURLString.range(of: "#access_token=")!
handleAuth(authToken: requestURLString.substring(from: range.upperBound))
return false;
}
return true
}
func handleAuth(authToken: String) {
print("Instagram authentication token ==", authToken)
}
}
struct API {
static let INSTAGRAM_AUTHURL = "https://api.instagram.com/oauth/authorize/"
static let INSTAGRAM_CLIENT_ID = "myclientidgoeshere"
static let INSTAGRAM_CLIENTSERCRET = " myclientsercretgoeshere "
static let INSTAGRAM_REDIRECT_URI = "http://www.dummyurl.com/just_a_made_up_dummy_url"
static let INSTAGRAM_ACCESS_TOKEN = ""
static let INSTAGRAM_SCOPE = "follower_list+public_content" /* add whatever scope you need https://www.instagram.com/developer/authorization/ */
}
enter image description here
U have used WKWebView and UIWebViewDelegate. It is not WKWebView delegate. This view has been inherited from UIView - not from uiwebview - that's why delegates methods does not work. Try to use WKNavigationDelegate with its methods.
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if let url = request.url, url.host == "URL FOR OAUTH GOES HERE" {
if url.absoluteString.range(of: "access_token") != nil {
let urlParts = url.absoluteString.components(separatedBy: "=")
let code = urlParts[1]
let userInfoURL = "https://api.instagram.com/v1/users/self/?access_token=" + code
//Make request with the userInfoURL to retrieve the user Info.
}
}
return true
}
We need "Access token" to go further.But it seems empty in your case.Try to run local server either through node/jupiter/MAMP or anything and check your localhost page is popping up.
Once your localhost is up and running.Please paste the below link in the browser by replacing the client_id to yours.
https://www.instagram.com/oauth/authorize/?client_id=Your_Client_Id&redirect_uri=http://localhost:8000&response_type=token&scope=public_content
Make sure you are giving the same redirect uri while you registered.
Please follow this link for further clarification
Click on Authorize in the page to be displayed in the browser.And check the URL in the browser, your access token would be passed for the next page.Copy this token and use it in the code
My app has a basic webview controller to perform some operations. This view in the storyboard is not much besides a wrapper around a UIWebView. The controller itself has various public functions that can be called to load pages in the webview, like so:
class WebViewController: UIViewController, UIWebViewDelegate {
// MARK: Properties
#IBOutlet var webView: UIWebView!
// MARK: UIViewController
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
loadHomePage()
}
// MARK: Public
public func loadHomePage() {
navigateWebView(to: HOME_PAGE)
}
public func loadSettingsPage() {
navigateWebView(to: SETTINGS_PAGE)
}
public func loadSignOutPage() {
navigateWebView(to: SIGN_OUT_PAGE)
}
// MARK: Private
private func navigateWebView(to url: String) {
let request = URLRequest(url: URL(string: url)!)
webView.loadRequest(request)
}
I'm trying to write unit tests that verify that the proper URL is sent to the loadRequest function of the webview. Note that I don't actually care about loading the URL; this is just a unit test, so all I really want to test is that loadSettingsPage sends a URLRequest with the SETTINGS_PAGE URL to the webview to load, for example.
I tried something like this, with no success:
_ = webViewController.view // Calls viewDidLoad()
XCTAssertEqual(webViewController.webView.request?.url?.absoluteString, HOME_PAGE)
The value of the first part of the assertEqual was nil.
I assume I need to mock out the webView somehow but I'm not sure how to go about that. Any suggestions?
As a follow-up, I'd also like to be able to test when things like webView.reload() and webview.goBack() are called, so any pointers there would be appreciated as well. Thanks!
I'm trying to check if the URL has changed in the webView. For example if I were to initially load a page like a Wordpress Sign In page, and I wanted to know when it changed and got redirected to the login page. I tried using this resource enter link description here but the answer seems to be incomplete and does not work.
func validateUrl (stringURL : NSString) -> Bool {
var urlRegEx = "((https|http)://)((\\w|-)+)(([.]|[/])((\\w|-)+))+"
let predicate = NSPredicate(format:"SELF MATCHES %#", argumentArray:[urlRegEx])
var urlTest = NSPredicate.predicateWithSubstitutionVariables(predicate)
return predicate.evaluateWithObject(stringURL)
}
urlTest is never called so i'm not sure the purpose of it.
if (validateUrl(stringURL: "http://google.com")) {
//will return true
print("Do Stuff");
}
else {
print("OTHER STUFf")
//If it is false then do stuff here.
}
And then to call this function
func webView(WebViewNews: UIWebView!, shouldStartLoadWithRequest request: NSURLRequest!, navigationType: UIWebViewNavigationType) -> Bool {
if (validateUrl(request.URL().absoluteString())) {
//if will return true
print("Do Stuff");
}
}
I added a return function at the end of my code, but the example does not include a return. I have very little experience in Webview, so any advice or help would be appreciated.
Use the webViewDidFinishLoad function of the UIWebViewDelegate to get the current URL loaded in your webview. Everytime the webview loads a URL the function webViewDidFinishLoad is called.
class YourClass: UIViewController, UIWebViewDelegate {
let initialURL = URL(string: "https://www.google.com.pe/")
#IBOutlet weak var webView:UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
webView.loadRequest( URLRequest(url: initialURL) )
}
func webViewDidFinishLoad(_ webView: UIWebView) {
if webView.request != URLRequest(url: initialURL!) {
//DO YOUR STUFF HERE
}
}
}
I'm a newbie on IOS development. Recently, I use UIWebView to load a webpage, and this is successful, and try to open links in it on the same UIWebView instance. However, after a click on some link, there's no response from UIWebView, and in xcode, it reports
2015-03-29 23:42:07.246 xxxxx[17349:1251340] Unknown result for URL http://www.xxxxxx.org/bugs/xxxxxx-xxxx-xxxxxx, for frame
I looked it up on Internet but I got little useful help. I know someone said to implement func webView in UIWebViewDelegate, but my app still doesn't work.
Can someone help me? I'm using the latest version of swift language. And a snippet of code is :
import UIKit
class ViewController: UIViewController, UIWebViewDelegate {
#IBOutlet weak var front: UIWebView!
func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType nt: UIWebViewNavigationType) -> Bool {
if (nt ==.LinkClicked){
return true
}
return true;
}
override func viewDidLoad() {
super.viewDidLoad()
UIWebView.loadRequest(self.front)(NSURLRequest(URL: NSURL(string: "http://www.google.com")!)) // Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Here is the sample Code :
UIWebView.loadRequest(webviewInstance)(NSURLRequest(URL: NSURL(string: "www.google.in")))