0

I have created a very simple app which directs the user to a web app... one of the pages within the app allows you to search store stock for various different stores (store number entered manually or the nearest store located automatically) and then asks the user to enter the appropriate barcode... within the app I have therefore added a barcode scanner (a separate view controller) which captures the barcode and then returns to the uiwebview... but how can I automatically enter that barcode into a certain div field and then execute a js function... I have tried evaluatejavascript but to very little avail... Almost given up, you're my last hope! :)

View controller as follows...

import UIKit
import WebKit


class ViewController: UIViewController {

    var webView: WebView




    @IBOutlet weak var searchText: UITextField!


    required init(coder aDecoder: NSCoder) {
        self.webView = WebView()
        super.init(coder: aDecoder)!
    }


    override func viewDidLoad() {
        super.viewDidLoad()
        view.addSubview(webView)
        webView.setPosition(view)
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    // MARK: Actions

    @IBAction func UseBCode(_ sender: Any) {
        webView.FillIn()
    }

    @IBAction func siteHomeBtn(_ sender: UIButton) {
        webView.setUrl("https://intranet.testsite.com/index.html")
    }

    @IBAction func searchBtn(_ sender: UIButton) {
        print ("Navigating to: \(searchText.text)")
        webView.setUrl(searchText.text)
    }

    @IBAction func appHomeBtn(_ sender: UIButton) {
        webView.setUrl("https://intranet.testsite.com/index.html")
    }

    @IBAction func backBtn(_ sender: UIButton) {
        webView.back()
    }


    @IBAction func forwardBtn(_ sender: UIButton) {
        //webView.forward()
    }

    @IBAction func unwindToHomeScreen(segue: UIStoryboardSegue) {
        dismiss(animated: true, completion: nil)
    //webView.FillIn()
        //webView.popup()

    }

    override func viewDidAppear(_ animated: Bool) {
        webView.FillIn()

    }

}


QRScannerController

import UIKit
import AVFoundation

var BCode = ""

class QRScannerController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {

    @IBOutlet var Back2: UIButton!

    @IBOutlet var topBar: UIView!

    @IBOutlet var messageLabel: UILabel!



    var captureSession:AVCaptureSession?
    var videoPreviewLayer:AVCaptureVideoPreviewLayer?
    var qrCodeFrameView:UIView?

    let supportedCodeTypes = [AVMetadataObjectTypeUPCECode,
                              AVMetadataObjectTypeCode39Code,
                              AVMetadataObjectTypeCode39Mod43Code,
                              AVMetadataObjectTypeCode93Code,
                              AVMetadataObjectTypeCode128Code,
                              AVMetadataObjectTypeEAN8Code,
                              AVMetadataObjectTypeEAN13Code,
                              AVMetadataObjectTypeAztecCode,
                              AVMetadataObjectTypePDF417Code,
                              AVMetadataObjectTypeQRCode]

    override func viewDidLoad() {
        super.viewDidLoad()

        // Get an instance of the AVCaptureDevice class to initialize a device object and provide the video as the media type parameter.
        let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)

        do {
            // Get an instance of the AVCaptureDeviceInput class using the previous device object.
            let input = try AVCaptureDeviceInput(device: captureDevice)

            // Initialize the captureSession object.
            captureSession = AVCaptureSession()

            // Set the input device on the capture session.
            captureSession?.addInput(input)

            // Initialize a AVCaptureMetadataOutput object and set it as the output device to the capture session.
            let captureMetadataOutput = AVCaptureMetadataOutput()
            captureSession?.addOutput(captureMetadataOutput)

            // Set delegate and use the default dispatch queue to execute the call back
            captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
            captureMetadataOutput.metadataObjectTypes = supportedCodeTypes

            // Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
            videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
            videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
            videoPreviewLayer?.frame = view.layer.bounds
            view.layer.addSublayer(videoPreviewLayer!)

            // Start video capture.
            captureSession?.startRunning()

            // Move the message label and top bar to the front
            //view.bringSubview(toFront: messageLabel)
            view.bringSubview(toFront: topBar)

            // Initialize QR Code Frame to highlight the QR code
            qrCodeFrameView = UIView()

            if let qrCodeFrameView = qrCodeFrameView {
                qrCodeFrameView.layer.borderColor = UIColor.green.cgColor
                qrCodeFrameView.layer.borderWidth = 2
                view.addSubview(qrCodeFrameView)
                view.bringSubview(toFront: qrCodeFrameView)
            }

        } catch {
            // If any error occurs, simply print it out and don't continue any more.
            print(error)
            return
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


    // MARK: - AVCaptureMetadataOutputObjectsDelegate Methods

    func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {

        // Check if the metadataObjects array is not nil and it contains at least one object.
        if metadataObjects == nil || metadataObjects.count == 0 {
            qrCodeFrameView?.frame = CGRect.zero
            //messageLabel.text = "No barcode detected"
            return
        }

        // Get the metadata object.
        let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject

        if supportedCodeTypes.contains(metadataObj.type) {
            // If the found metadata is equal to the QR code metadata then update the status label's text and set the bounds
            let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
            qrCodeFrameView?.frame = barCodeObject!.bounds

            if metadataObj.stringValue != nil {
                messageLabel.text = "Use " + metadataObj.stringValue

                // Copy the barcode text to the clipboard.
                let clipboard = UIPasteboard.general
                clipboard.string = metadataObj.stringValue
            view.bringSubview(toFront: messageLabel)

                BCode = metadataObj.stringValue


                }

            }
        }
    }

Webview.script... the fillin function is me playing (to very little avail! :(

import UIKit
import WebKit

class WebView : WKWebView {

    /**
     Initialize the WKWebView.
     */
    init(){
        let webConfig:WKWebViewConfiguration = WKWebViewConfiguration()
        super.init(frame:CGRect.zero,configuration:webConfig)
        self.translatesAutoresizingMaskIntoConstraints = false
        self.allowsBackForwardNavigationGestures = true

        createHomePage()
    }


    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    /**
     Set the position for the WKWebView.
     */
    func setPosition(_ view: UIView) {
        self.translatesAutoresizingMaskIntoConstraints = false;
        let height = NSLayoutConstraint(item: self, attribute: .height, relatedBy: .equal, toItem: view, attribute: .height, multiplier: 1, constant: -60)
        let width = NSLayoutConstraint(item: self, attribute: .width, relatedBy: .equal, toItem: view, attribute: .width, multiplier: 1, constant: 0)
        let top = NSLayoutConstraint(item:self,attribute: .top, relatedBy: .equal, toItem: view, attribute: .top, multiplier: 1, constant: 20)
        view.addConstraints([height, width, top])
    }

    /**
     Set the url the webview should display.
     */
    func setUrl(_ url:String!) {
        if url != nil {
            let url = URL(string:url)
            let request = URLRequest(url:url!)
            self.load(request)
        }
    }

    /**
     Create the home page.
     */
    func createHomePage() {
        self.setUrl("https://intranet.testsite.com/index.html")
        drawHomePage()
    }

    /**
     Draw the home page.
     */
    func drawHomePage() {
        let javaSCriptString="document.body.style.background=\"#ffc\""
        //self.loadHTMLString("<h1>Top20</h1>", baseURL: nil)
        self.evaluateJavaScript(javaSCriptString, completionHandler: nil)
    }

    /**
     Go to the home page.
     */
    func setAppHome() {
        print("The first item is \(self.findFirstItem()?.url)")
        let item = findFirstItem()
        if item != nil {
            self.go(to: item!)
            drawHomePage()
        }
    }

    /**
     Find the first item in the list of websites.
     */
    func findFirstItem() -> WKBackForwardListItem? {
        var index=0
        if (self.backForwardList.item(at: 0)==nil) {
            return nil
        }
        while self.backForwardList.item(at: index) != nil {
            index -= 1
        }
        return self.backForwardList.item(at: index+1)
    }

    /**
     Handle forward navigation.
     */
    func forward() {
        if self.canGoForward {
            self.goForward()
        } else {
            print("Cannot go forward.")
        }
    }

    /**
     Handle backward navigation.
     */
    func back(){
        if self.canGoBack {
            self.goBack()
            //self.evaluateJavaScript("document.getElementByID('barcode').innerHTML = '" + BCode + "'", completionHandler: nil)
        } else {
            print("Cannot go backwards.")
        }
    }

    func FillIn() {

        // fill data
        //let savedUsername = "USERNAME"
        //let savedPassword = "PASSWORD"
        let javaSCriptString="document.getElementByID('barcode').innerHTML = '" + BCode + "'"
        //self.loadHTMLString("<h1>Top20</h1>", baseURL: nil)
        self.evaluateJavaScript(javaSCriptString, completionHandler: nil)

        self.evaluateJavaScript("document.getElementByID('barcode').innerHTML = '" + BCode + "'")

        let source="appfunction('" + BCode + "'"
        //self.loadHTMLString("<h1>Top20</h1>", baseURL: nil)
        self.evaluateJavaScript(source)

        self.evaluateJavaScript("document.getElementByID('barcode').innerHTML = '" + BCode + "'")
        //let javaSCriptString="functiontofindIndexByKeyValue(eval('BarCode'), 'label', '\(BCode)', 'value')"


        let PArt = self.evaluateJavaScript(javaSCriptString)

        let DC01Stock = self.evaluateJavaScript("functiontofindIndexByKeyValue(eval('DCStock'), 'PArt', PArt.value, 'DC01')")

    }
    func webView(webView: WKWebView!, didFinishNavigation navigation: WKNavigation!) {
        UIApplication.shared.isNetworkActivityIndicatorVisible = false

        webView.evaluateJavaScript("document.getElementById('anonymousFormSubmit').click();", completionHandler: nil)

    }


}
L777
  • 7,719
  • 3
  • 38
  • 63

1 Answers1

1

Check this question and responses:

Calling Javascript using UIWebView

  1. Create a js method to receive your barcode.
  2. When the page is already loaded, you can call it by using stringByEvaluatingJavaScriptFromString.

    let codebar = "34244342342424234" webView.stringByEvaluatingJavaScriptFromString("methodName("\(codebar)");")


Update

I used this method some time ago: evaluateJavaScript in WKWebView, this example loads a jQuery and then change the background:

var navigator : WKWebView!

func runJS(js:String) {
    navigator.evaluateJavaScript(js) {
        res, error in
        print(res ?? "no res", error ?? "no error")
    }
}

@IBAction func changeBackground(_ sender: Any) {
    navigator.evaluateJavaScript("jQuery('body').css('background', 'magenta!important')") {res, error in print(error ?? "no error buton 1")}
}


@IBAction func loadJQuery(_ sender: Any) {
    //Load jQuery library using plain JavaScript
    runJS(js: "(function(){ " +
        "var newscript = document.createElement('script'); " +
        "newscript.type = 'text/javascript'; " +
        "newscript.async = true; " +
        "newscript.src = 'https://ajax.googleapis.com/ajax/libs/jquery/1.6.1/jquery.min.js'; " +
        "(document.getElementsByTagName('head')[0]||document.getElementsByTagName('body')[0]).appendChild(newscript); " +
    "})();")
}
Community
  • 1
  • 1
ucotta
  • 557
  • 4
  • 7
  • Thank you ucotta, that was pretty much what I constantly found online but it still refused to work... in the end after following your link (And another within, so on a so forth) there was a suggestion to debug the uiwebview via safaris developer function... Which led me to find a problem with the JS (Very embarrassing!!) thus why I wasn't getting any errors from xcode :-/ – Russell Oakes Feb 16 '17 at 08:27
  • I checked an old application and I found it: webview.evaluateJavaScript("jQuery('body').css('background', 'magenta!important')") {res, error in print(error ?? "no error buton 1")} I hope this other example works for you! – ucotta Feb 17 '17 at 04:14