The WebKit in IOS9 and the surprise of Safari _ios

Source: Internet
Author: User
Tags constant javascript array

Each used UIWebView iOS developer has deep feelings about its limitations and limited functionality. Xingran, it will change the dilemma after IOS8 launched the WebKit framework. In this article I will go deep into the webkit to experience the benefits it brings us, while also looking at the new iOS9 in the Sfsafariviewcontroller some new surprises.

Common browsing behavior

The so-called general browsing behavior can be summed up in the following several:

Web page Load Progress
Forward
Back off
Refresh

If every app that uses WebView has to do a dedicated controller, it's also a hassle, and I used to do it directly with other Third-party-written packages.

But now, if you're going to be handy with Wkwebview, say it in code:

Class Viewcontroller:uiviewcontroller {var webview:wkwebview!
    
  @IBOutlet weak var progressview:uiprogressview!
    
    Required Init (coder Adecoder:nscoder) {super.init (Coder:adecoder)! instantiated Wkwebview Self.webview = Wkwebview (Frame:cgrectzero)} override func Viewdidload () {Super.viewdi
    Dload ()//coding to join Wkwebview View.addsubview (webview) View.insertsubview (WebView, Abovesubview:progressview) Webview.translatesautoresizingmaskintoconstraints = False Let Widthconstraint = Nslayoutconstraint (item:webVie W, attribute:. Width, Relatedby:. Equal, Toitem:view, attribute:. Width, Multiplier:1, constant:0) view.addconstraint (widthconstraint) Let Heightconstraint = Nslayoutconstr Aint (item:webview,attribute:. Height, Relatedby:. Equal,toitem:view, attribute:. Height, Multiplier:1, constant: -46) view.addconstraint (heightconstraint)//Detect changes to WebView object Properties Webvie W.addobserver (self, Forkeypath: "Loading", Options:. New, Context:nil) webview.addobserver (self, Forkeypath: "title", Options:.
    
    New, Context:nil)//Loading web page Let request = Nsurlrequest (Url:nsurl (string: "http://ray.dotnetage.com")!) Webview.loadrequest (Request)} override Func Observevalueforkeypath (keypath:string?, Ofobject Object:anyo

      Bject?, change: [String:anyobject]?, context:unsafemutablepointer<void>) {if (KeyPath = = "Loading") { Detection button Availability forwardbutton.enabled = Webview.cangoback backbutton.enabled = Webview.cangoback stopbut Ton.image = webview.loading?  UIImage (Name: "Cross"): UIImage (named: "Syncing")} else if KeyPath = "title" {title = Webview.title} else if KeyPath = = "Estimatedprogress" {Progressview.hidden = Webview.estimatedprogress = 1 PROGRESSVIEW.S Etprogress (Float (webview.estimatedprogress), Animated:true)}}}

The code I think there is nothing to say, in addition to Wkwebview can not be visualized through the IB to build, the above code is the AutoLayout part of the code optimization is the. Write a write, do a Example to understand.

Communicating with Javascript

By WebKit, you don't need to communicate with the DOM through a JavaScript bridge. In fact, this is not a new technology, early Windows98 in VB or in Delphi can also use the COM interface in a completely similar manner with the DOM communication.

Don't say much nonsense, talk about the basic principles of WebKit. The following is a schematic diagram of the communication relationship between the web process of WebKit Host and the APP master process:

This contains two processes

Executing JavaScript scripts

We can include JavaScript scripts within the Bundle of the app as application resources. Inject it through WebKit into the target Web page at run time.

First we have to prepare a target page, and here is a sample of my own blog (http://ray.dotnetage.com). Open it in the App with WebKit.

Now, I will be the first page of my blog to change the text of the headline, the specific code is very simple:

$(".page-header h1").text("iOS注入测试");

Then, add a script file called in the iOS project to inject.js copy the code.

JavaScript scripts included in the App are best executed once in the console of the browser to ensure that the script itself can be executed correctly. If the script contains a potential error, it is not detectable in the app.

Then, create an instance within the Controller's constructor WKWebViewConfiguration and pass in the constructor as a parameter WKWebView , as follows:

Viewcontroller.swift

Import WebKit

class Viewcontroller:uiviewcontroller {

	var webview:wkwebview!

	Required Init (coder Adecoder:nscoder) {
	  super.init (coder:adecoder)!
	  

	  Let configuation = Wkwebviewconfiguration ()

	  Configuation.userContentController.addUserScript (Getuserscript (" Inject "))
	  
	  Self.webview = Wkwebview (frame:cgrectzero,configuration:configuation)
	}

  //read from Resource JavaScript script
  func getuserscript (fromname:string)-> wkuserscript {let
    FilePath = Nsbundle.mainbundle (). Pathforresource (FromName, OfType: "JS") let
    js = try! String (contentsoffile:filepath!, encoding:nsutf8stringencoding) return
    wkuserscript (Source:js, Injectiontime : . Atdocumentend, Formainframeonly:true)
  }

Another point to note in this code snippet is the getUserScript() object returned by the custom method WKUserScript . We can injectionTime decide to inject the script into the beginning of the HTML or at the end of the document.

Execute the code again with the following effect:

That is, we can control all the DOM objects in the page arbitrarily after we inject JavaScript through WebKit in the app!

JavaScript callback

In addition to injecting code into the browser from one end of the app, perform an action. In some cases we also need to do some processing from the Web page, such as reading some elements of the Web page and turning them into a collection of JSON objects, back to App processing. Or maybe our app wants to read all the images in the page one at a time after loading a Web page, and when the user clicks on the images we use the app's local way to preview the screen, and so on. In these contexts:

We all have to return the object from the page.

In other words, to communicate with the app process within the process of a Web page, we need to use the script in:

webkit.messageHandlers.{MessageName}.postMessage([params]);

This method cannot be executed directly in a standard HTML5 browser, such as Chrome and Safair. This object is only available on pages that are WebKit Host webkit . It's not hard to understand, but WebKit injected this instance into Windows after loading the page webkit , allowing JavaScript to send information to the app.

If we're going to send a message to the app, such as: After a button is clicked on the page, to execute the code that opens the album in the app, you have to write the code in JavaScript first:

$ ("#mybutton"). Click (function () {
  webkit.messageHandlers.openPhotoLibrary.postMessage ();
});

Please note that openPhotoLibrary This object is not in swift, when this method is sent back to Swift this is just the name of a message, and in Swift to receive this to the browser to send the information our controller needs to implement WKScriptMessageHandler this interface, there is only one way, Let's take a little more space to open the code for this interface directly:

/*! A class conforming to the Wkscriptmessagehandler protocol provides a for
 receiving messages from JavaScript run Ning in a webpage.
 */Public
protocol Wkscriptmessagehandler:nsobjectprotocol {
  
  /*! @abstract invoked when a script message is Rece Ived from a webpage.
   @param usercontentcontroller The User Content controller invoking the
   delegate method.
   @param the script message received.
   * *
  @available (IOS 8.0, *) public
  func Usercontentcontroller (usercontentcontroller:wkusercontentcontroller , Didreceivescriptmessage message:wkscriptmessage)
}

So, we're going to implement this interface directly:

Class Viewcontroller:uiviewcontroller, Wkscriptmessagehandler {


  required init (coder Adecoder:nscoder) {

    // ... Previous Code IBID.

    Configuation.userContentController.addScriptMessageHandler (self, Name: "Openphotolibrary")

    Self.webview = Wkwebview (frame:cgrectzero,configuration:configuation)
  }

  ...


  Func Usercontentcontroller (Usercontentcontroller:wkusercontentcontroller, Didreceivescriptmessage message: Wkscriptmessage) {
    if message.name = = "Openphotolibrary" {
      //Here you can add the code to open the album}
  }

From the code you can see the principle of one or two:

WKWebViewto addScriptMessageHandler register a message name with a method before constructing the configuration object, the routine here is "openphotolibrary".
Implements WKScriptMessageHandler the interface, judging the source of the message from the userContentController() parameters of the method message.name , and executing the corresponding code.

In addition, if we need to pass an object to the app from a JavaScript script, you can postMessage() enter the object as a parameter directly within the method, but usually the type of the argument should be an array or a normal JSON object, so that the app can read it from the Dictionary object.

For example, I read the address and name of all the menus from the current Web page and generated a menus JavaScript array object:

var menus = $ (". NavBar a"). Map (function (n,i) {return
  {
    title: $ (N). Text,
    Link: $ (n). attr ("href")
  };
} );

Webkit.messageHandlers.didFetchMenus.postMessage (menus);

Here we skip the interface implementation and look directly at the implementation of the userContentController method:

var menus: [menus]?

Func Usercontentcontroller (Usercontentcontroller:wkusercontentcontroller, Didreceivescriptmessage message: Wkscriptmessage) {
  if message.name = = "Didfetchmenus" {
    if let resultarray = Message.body as? [Dictionary<string,string>] {
      menus = resultarray.map{Menu (dict: $)}

      //Check out and convert JSON to Swift's Menu object
      print (menus)
    }
  }
}

The Safair browser in iOS9

This new module has been added to the iOS9 SafariServices to provide a fully functional inline Safair
SFSafariViewControllercan be used like a normal controller.

The following is a simple example

Import uikit
Import safariservices

class Viewcontroller:uiviewcontroller {
  @IBAction func openbrowser ( Sender:anyobject) {let
    safari = Sfsafariviewcontroller (Url:nsurl (string: "http://www.apple.com")!)
      
    Self.showviewcontroller (Safari, sender:self)
  }
}

SFSafariViewControllerThe biggest difference with WebKit is that SFSafariViewController there is no controllable method, just a controller that can be completely embedded in the app, avoiding the same as before if you open an external link to jump out of the current app, and SFSafariViewController all the features embedded in Safari and Safari are , the same features as 3D touch and page cutting are also supported. And when our app uses an external network account for integrated login, Safari gets more direct access to the current app's application context without having to jump out of the back and back to app. This is a big boost to the app's experience when it comes to integrating with Safari.

On Apple's developer website, the WebKit and safariservices choices are given:

Select WebKit if you want to interact with a Web page
If you need to have the same experience with Safari and do not need to interact with Web pages to recommend using Safariservices

This is a really good update.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.