July 17, 2014

Objective-C WKWebView to JavaScript and Back

Posted in iPhone development, mac development tagged , , , , at 4:50 pm by tetontech

 In a previous post I showed how to communicate from JavaScript to Swift and back. This posting is a direct, line-by-line conversion of that code into Objective-C. This code example shows how to use the new WKWebView rather than the old UIWebView with Objective-C.

Since WKWebView doesn’t yet show up as a drag-and-droppable view in Interface Builder, a WKWebView instance is created in the ViewController’s viewDidLoad method. The WKWebView instance is then sized to fill the entire view of the device. This can cause usability problems since the WKWebView’s content now overlaps the header bar. If I was creating an app to ship, I would use Interface Builder to add a UIView, create an IBOutlet to that view, and size the UIView to fit the display portion of the screen. I would then add the WKWebView to the UIView I added using Interface Builder.

The header file for the ViewController class shows how to include the WebKit headers and make the ViewController a WKScriptMessageHandler. The ViewController needs to be a WKScriptMessageHandler since, in this example, the ViewController is going to be sent messages from the JavaScript code.

#import <UIKit/UIKit.h>
#import <WebKit/WebKit.h>
@interface ViewController : UIViewController <WKScriptMessageHandler>
   
@end

In order to create the WKWebView and add it to the main view in viewDidLoad and later use the same WKWebView in userContentController:didReceiveScriptMessage method a WKWebView property called theWebView is added to the ViewController class.

The ViewController’s viewDidLoad method includes the creation of an instance of WKWebViewConfiguration. Among other things, WKWebViewConfiguration is used to setup and name the JavaScript message listener. This setup is done with the WKWebViewConfiguration userContentController’s addScriptMessageHandler:name method. For this example I’ve chosen ‘interOp’ as the name to be exposed to JavaScript for the message handler and used the ViewController as the message handler.

#import "ViewController.h"

@interface ViewController ()
    @property(strong,nonatomic) WKWebView *theWebView;
@end

@implementation ViewController
            
- (void)viewDidLoad {
    [super viewDidLoad];
    NSString *path = [[NSBundle mainBundle] pathForResource:@"index" ofType:@"html"];
    NSURL *url = [NSURL fileURLWithPath:path];
    NSURLRequest *request = [NSURLRequest requestWithURL:url];
    
    WKWebViewConfiguration *theConfiguration = 
          [[WKWebViewConfiguration alloc] init];
    [theConfiguration.userContentController 
          addScriptMessageHandler:self name:@"interOp"];
    
    _theWebView = [[WKWebView alloc] initWithFrame:self.view.frame 
                      configuration:theConfiguration];
    [_theWebView loadRequest:request];
    [self.view addSubview:_theWebView];
    
}

Since ViewController is a WKScriptMessageHandler, as declared in the ViewController interface, it must implement the userContentController:didReceiveScriptMessage method. This is the method that is triggered each time 'interOp' is sent a message from the JavaScript code.
- (void)userContentController:(WKUserContentController *)userContentController 
                            didReceiveScriptMessage:(WKScriptMessage *)message{
    NSDictionary *sentData = (NSDictionary*)message.body;
    int aCount = [sentData[@"count"] integerValue];
    aCount++;
    [_theWebView evaluateJavaScript:[NSString 
            stringWithFormat:@"storeAndShow(%d)", aCount] completionHandler:nil];
}

In the example code above you can see a WKScriptMessage is received from JavaScript. Since WKWebKit defines JSON as the data transport protocol, the JavaScript associative array sent as the message's body has already been converted into an NSDictionary before we have access to the message. We can then use this NSDictionary to retrieve an int that is the value associated with the 'count' label. The JSON conversation creates NSNumbers for numeric type values so the code example retrieves the NSNumber's intValue, modifies it, and then sends the modified value back to JavaScript. 

One of the very nice features of WKWebKit framework is that the WKWebView runs independently of the main, or User Interface, thread. This keeps our apps responsive to user input. The storeAndShow method will not execute in the app's main thread. 

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}

@end

The JavaScript examples below show how to send a message to Objective-C using webkit’s list of messageHandlers and the interOp handler we setup in the ViewController’s viewDidLoad method. An example of this is found in the sendCount JavaScript function. The storeAndShow function that is triggered is strait forward. All that function does is some standard JavaScript using the DOM (Document Object Model).

var count = 0

function sendCount(){
    var message = {"count":count}
    window.webkit.messageHandlers.interOp.postMessage(message)
}

function storeAndShow(updatedCount){
    count = updatedCount
    document.querySelector("#resultDisplay").innerHTML = count
}

Overall I am really pleased with the new WKWebView and the other classes in the WKWebView framework when it is compared to the old UIWebView. I like the WKWebView executing outside the main thread. I like the choice of JSON for the data transfer protocol. The adding of the message handlers is a little awkward, but nothing is ever perfect.

July 15, 2014

Swift to JavaScript and JavaScript to Swift. A round trip.

Posted in Uncategorized tagged , , , , , at 9:12 pm by tetontech

In a previous post I showed how to make a call from JavaScript to Swift. Take a look there for a more in-depth discussion of the code to accomplish that data transfer. This example expands on what I did in that post by showing how to make a call from JavaScript to Swift, do a calculation, and then pass the results back to JavaScript. The source code is very similar. It uses one method, evaluateJavaScript(), of the WKWebView class that wasn’t available in Apple’s previous Swift beta.

In the view controller’s userContentController method we’ll need to have access to the WKWebView created in the viewDidLoad method. This requires the addition of a WKWebView attribute to the ViewController class. After trying a couple of experimental ideas I remembered the correct, Swifty way to do this. I couldn’t create the WebView on the same line as the attribute was declared since the initializer for the WKWebView isn’t as simple as adding some integer attribute (var someInt = 3). Instead the initializer needs a frame and a WKWebViewConfiguration. Because of this the WKWebView must be initialized in the viewDidLoad method (This may change if Apple adds a WKWebView to Interface Builder).

The Swift way to declare an attribute and initialize it in something other than an init method is to make the attribute optional using the ? operator.

class ViewController: UIViewController, WKScriptMessageHandler {
    
    var theWebView: WKWebView?
}

In the viewDidLoad method the WKWebView can now be created using the WKWebView function. Once theWebView has been set, the ! operator is needed to declare that we know theWebView attribute is not nil.

    override func viewDidLoad() {
        super.viewDidLoad()
        var path = NSBundle.mainBundle().pathForResource("index", 
                               ofType: "html")
        var url = NSURL(fileURLWithPath: path)
        var request = NSURLRequest(URL: url)

        var theConfiguration = WKWebViewConfiguration()
        theConfiguration.userContentController.addScriptMessageHandler(self, 
                                   name: "interOp")

        theWebView = WKWebView(frame: self.view.frame, 
                             configuration: theConfiguration)
        theWebView!.loadRequest(request)
        self.view.addSubview(theWebView)

    }

As in the previous example, the userContentController() method must be implemented to handle the messages captured by the script message handler that was added to theConfiguration. In this example the message’s body, the data sent from the JavaScript is interpreted as an NSDictionary since the JavaScript sends an associative array.

    func userContentController(userContentController: 
       WKUserContentController!,
       didReceiveScriptMessage message: WKScriptMessage!) {
        
        let sentData = message.body as NSDictionary
        let aCount:Int = Int(sentData["count"] as NSNumber)
        
        theWebView!.evaluateJavaScript("storeAndShow( \(aCount + 1) )", 
                                        completionHandler: nil)
    }

The other change to the previous example is the addition of the call to theWebView’s evaluateJavaScript method. It has two parameters; a string that is the Javascript to be executed, and a function or closure that will be notified once the JavaScript completes. In this example I don’t need to know when the JavaScript completes so I passed nil as the second parameter.

The javascript for this example is strait forward; an onclick listener function to send a message to the Swift message handler, and the storeAndShow function that the Swift code will call to send a message back to the JavaScript.

var count = 0

function sendCount(){
    var message = {"count":count}
    window.webkit.messageHandlers.interOp.postMessage(message)
}

function storeAndShow(updatedCount){
    count = updatedCount
    document.querySelector("#resultDisplay").innerHTML = count
}

For my own code I would send a Dictionary back to the JavaScript where it would be used as an associative array. I left that out of this example since I didn’t think it was necessary to show.

Overall, the interaction between Swift and Javascript using the WKWebView is more strait forward than using the old UIWebView. It is nice to have a JavaScript way to directly call to Swift. I also like the selection of JSON as the data transfer format for the JS to Swift communication. It reflects the decision I made to adopt that format for QCHybrid years ago. It would be better if the values in the dictionary knew their type so casting using the as operator wasn’t needed but I can live with it the way it is.

July 7, 2014

Swift, C libraries, and a Speed Test

Posted in iPhone development, mac development tagged , , , , , , , , , at 7:20 pm by tetontech

In a previous post I showed how to statically link a C library into a Swift app. I mentioned in that posting that converting data for use in libraries written in other languages can be costly. I have done some testing by passing 3 basic data types between Swift and C. The results are very interesting and not what I would have predicted based on calling C functions from other languages I’ve used.

The three types I tested were Ints, Doubles, and Strings. I did the test by calling an echo function for each type in both Swift and C. I supposed that calling the C echo function would be slower that calling the Swift echo function in each case. This was not so. It was faster to convert a Swift Int to a c int, pass it to a C function, and then convert the returned C int into a Swift Int than to call the Swift echo function that required no conversion. The difference was not huge, around 300 milliseconds for 100,000,000 calls, but it was consistent.

Doing conversions for Doubles, passing them to a C function, and converting the resultant c double to a Swift Double was also faster than calling a Swift function that echoed a Swift double it was passed. Once again the difference was not huge. There was around an 80 millisecond difference.

The Swift String to char* conversion is messy so I figured converting a Swift string and passing a char*  would be slow. It was so slow that I reduced the number of function calls I was timing to 1,000,000. Making that many calls it was around 12 times slower to convert a Swift String to a char*, pass the char* to C, and convert the resultant char* back to a Swift String.

So what conclusions do I draw? The compiler is currently optimizing C calls requiring number conversions slightly more effectively than the Swift calls. Because of this, if all I’m passing are simple things like Ints and Doubles I can go ahead and use C libraries without much concern. If I’m passing more complex things like Strings or Structs, I would avoid using them in C calls when possible.

Here is the code for the Swift and the C echo functions.

    //Swift
    func doSwiftIntStuff(anInt:Int) -> (Int){
        return anInt
    }
    func doSwiftDoubleStuff(aDouble:Double) -> (Double){
        return aDouble
    }
    func doSwiftStringStuff(aString:String) -> (String){
        return aString
    }
    //C
    int doIntStuff(int anInt){
        return anInt;
    }

    char* doStringStuff(char* aStr){
        return aStr;
    }

    double doDoubleStuff(double aDouble){
        return aDouble;
    }

Here is an example of converting and passing a Swift Int

    var initialTime = NSDate()
    let aNum = 3
    for index in 0..100_000_000 {
        let aResult = Int(doIntStuff(Int32(aNum)))
    }
    println("Swift result C int: \(initialTime.timeIntervalSinceNow)")

Here is an example of converting and passing a Swift String. Notice that this example will only handle ASCII strings.

initialTime = NSDate()
for index in 0..1_000_000 {
    var ascii = aString.dataUsingEncoding(NSASCIIStringEncoding, 
                allowLossyConversion:true)
    var stringAsChars = CChar[](count:ascii.length, repeatedValue:CChar(0))
    ascii.getBytes(&stringAsChars, length:ascii.length)
    stringAsChars.append(CChar(0))
    let aResult:String = String.fromCString(doStringStuff(&stringAsChars))
}
println("Swift result C string: \(initialTime.timeIntervalSinceNow)")

July 3, 2014

Swift and Statically Linking C libraries

Posted in iPhone development, mac development tagged , , , , at 5:26 pm by tetontech

In preparation for creating a simulation engine more robust and current than the simple one I described in a previous post I decided to do some sandboxing of how to statically link and use an existing C library.

Rather than use something complex I created a simple C library that has one function, doStuff. This function is declared in the StuffStatic.h header file

//
//  StuffStatic.h
//  StuffStatic
//

int doStuff(int anInt);

 

and defined in the StuffStatic.c implementation file.

//
//  StuffStatic.c
//  StuffStatic
//

#import <stdio.h> 
#import "StuffStatic.h"

int doStuff(int anInt){
    int result = anInt * 2;
    printf("the result is %d\n",result);
    return result;
}

This code was compiled into libStuffStatic.a.

To use this library in a Swift app I added the libStuffStatic.a file and the StuffStatic directory containing the StuffStatic.h file to the project by dragging them into the Supporting Files group.

Interestingly, Xcode didn’t ask if I wanted to add the bridging header file I knew would be needed to make the C calls from within Swift. Rather than go through the process of manually adding a bridging file I used Xcode to create a junk.c file. This triggered the creation of the bridging header file and made all of the changes to the project required to use it. I then deleted the junk.c file from my project.

The bridging header file is used to do an import of the header files for the library. Any header from the library you include in this file automatically makes available anything defined in it to Swift. Because of this you can make calls to the functions in the header files directly in any Swift file without worrying about doing an include statement.

Since my swift project was just a sandbox project I decided to use the doStuff function directly in the ViewController’s viewDidLoad method. I wanted to simulate a number being calculated in Swift, passed to C, and a returned C int being used in Swift.

override func viewDidLoad() {
        super.viewDidLoad()
        let aNum = 3
        let aResult = Int(doStuff(Int32(aNum)))
        println("Swift result: \(aResult)")
    }

Xcode won’t do autoboxing for us so we have to do it ourselves. To convert the Swift Int aNum to a C int I passed aNum to the Int32 constructor. doStuff could then use it directly. Since doStuff returns a C int I passed its result to Swifts Int constructor and stored the new Swift Int in the aResult constant.

When data types are bridged between languages there is a computational speed cost. I haven’t yet tested what this cost is for Swift-to-C and C-to-Swift bridging. That is on my plate for next week.

June 30, 2014

Swift, NSOperationQueues, Closures, and Threading

Posted in iPhone development, mac development tagged , , , at 3:49 pm by tetontech

In a previous posting I showed how to inherit from NSOperation to do work in background processes using NSOperationQueues. In another, I showed how to use Grand Central Dispatch, GCD, to do threading. In this post I’ll give a simple example of using NSOperationQueues without NSOperations.

For this example I created a single view application, added a label to the view using Interface Builder, and added an IBOutlet for the label called ‘theLabel’ to the ViewController for the view. theLabel can only be updated by the main application thread. This means that inside the code running in the background there must be a a call that runs code in the main application thread.

To take advantage of Swift’s closures, this example uses the NSOperationQueue method called ‘addOperationWithBlock.’ Blocks are the Objective-C equivalent to Swift’s closures. Line’s 2 and 4 show the addOperationWithBlock method being used.

Line 2 adds a closure to a background queue that was created on line 1. The code in the closure will be run on a background thread. Line 4 adds a closure to the main thread’s queue for execution. Line 4 does this by taking advantage of the NSOperationQueue class method ‘mainQueue.’ mainQueue returns the queue for the application’s main thread. This means that anything in the closure defined on lines 4 – 6 will execute in the application’s main thread.

1       var backgroundQueue = NSOperationQueue()
2       backgroundQueue.addOperationWithBlock(){
3           println("hello from background")
4           NSOperationQueue.mainQueue().addOperationWithBlock(){
5               self.theLabel.text = "updated from main thread"
6           }
7       }

By creating a closure within a closure you can execute code in a background thread and after it has completed you can execute code in the main or ‘UI’ thread. You can also use if statements to update the UI in different ways depending on what happens in the background thread.

 

June 25, 2014

Swift, Objects, Arrays, and Simulation

Posted in iPhone development, mac development, simulation tagged , , , , at 9:24 pm by tetontech

One of the tasks I give myself when learning a new language is to write a traditionally designed discrete event simulation engine. This is due to my background in creating and supporting simulation software for the semi-conductor industry. Another reason is that it gives me a frame of reference I’m comfortable with and allows me to focus on how the different parts of the new language interact with each other.

To highlight certain Swift concepts and how they can interact I’ll go over some of my simulation engine’s code. The entire code set is available on gitHub in the SimSwift-Traditional repository. It includes 3 files – Engine.swift, Event.swift, and ViewController.swift.

The simplest file is Event.swift so let’s start there. It describes the Event class, its attributes, and its behaviors.

The Event class has two constant properties, an integer that represents the time that the event should occur, and a closure or function that is the action to be taken at that time. The trigger time is used by the engine to sort and group events that need to happen. I chose Int as the datatype to allow maximal flexibility for the engine. Time in the engine could be milliseconds since the unix epoch time. It could also be zero based and have each event trigger at some number of seconds, milliseconds, hours, days, or some other offset from the beginning of the simulation.

 24 import Foundation
 25 
 26 class Event{
 27     let triggerTime:Int
 28     let action:()->()
 29 
 30     init(aTriggerTime:Int, anAction:()->()){
 31         triggerTime = aTriggerTime
 32         action = anAction
 33     }
 34 }

The Event class includes an init method. Swift classes need to have init methods to set properties. If you don’t declare an init method Swift will not generate a default at compile time in most cases. In the init method  the parameters are assigned to their matching properties. You also see that the parameters are named parameters. This means that when init is called the parameter names are used to delimit the parameters. I’ll show you how to use the delimiters when we look at some of the code in the ViewController.swift file.

The simulation engine class, TraditionalEngine, has three variable properties. The time property represents the ‘current’ time of the simulation, futures are events that need to happen at some future time, and presents are events that have trigger times that match the ‘current’ time of the simulation.

class TraditionalEngine{
    
    var time:Int
    var futures:Array<Event>
    var presents:Array<Event>
    
    init(startTime:Int){
        time = startTime
        futures = Array<Event>()
        presents = Array<Event>()
    }

The init method for the TraditionalEngine class has one named parameter, startTime. startTime represents the initial time of the simulation. The futures and presents arrays are set to empty arrays so events can be added later.

I’ve given the engine an addEvent method. It has one named parameter, an. One purpose of the addEvent method is to determine if the event should be added to the presents or the futures array. Which it is added to depends on if the event’s triggerTime is after the current time of the simulation.

    func addEvent(an:Event){
        an.triggerTime > time ? insertEvent(an, isFuture: true)
                                     : insertEvent(an, isFuture: false)
    }

I chose to use Swift’s ternary operator ( ? : ) for reasons of succinctness. If the event’s trigger time is greater than the simulation’s current time the event is inserted into, not appended to, the futures array, otherwise it is inserted into the presents array. In either case a binary search insertion is performed.

Why do insertion in the presents list? From industry experience I know that events users setup to start simulations sometimes happened in the past. By using an insertion based approach, events in the past will be triggered before the current ones. Let’s look at the code that does the insertion later. First we’ll take a look at the simulation’s run loop found in the engine’s go method.

While there are events waiting in the future or events for the current time the simulation loop continues. In the loop any present events are triggered and then the next group of events are found, executed, and the loop continues. This is the heart of any traditionally designed simulation engine.

    func go(){
        while(self.futures.count > 0 || self.presents.count > 0){
            self.doAnyPresents()
            self.doNextGroup()
        }
    }
    
    func doAnyPresents(){
        while presents.count > 0 {
            presents.removeAtIndex(0).action()
        }
    }
    
    func doNextGroup(){
        if futures.count > 0 {
            let nextPresent = futures.removeAtIndex(0)
            self.time = nextPresent.triggerTime
            nextPresent.action()
            while futures.count > 0 
                  && futures[0].triggerTime == self.time{
                futures.removeAtIndex(0).action()
            }
        }
    }

The doNextGroup method pops the first event off the futures array and sets the simulation’s current time to the popped event’s triggerTime. This is what causes time to move forward in the simulation. Thankfully, it also means we don’t need to simulate the time between events when nothing is happening. The doNextGroup method executes all events that match the current time.

Why then does the simulation loop always call doAnyPresents before calling doNextGroup? In discrete event simulations it is common for events to create new events that have the same trigger time as the current time. Rather than make the programmer using the simulation’s API write if statements all over in their code they can use the addEvent method and not have to worry about which Array to add it to. If the event has a trigger time that matches the simulation’s current time it will end up in the currents Array and be executed before the simulation moves on to the next group of events.

Rather than put a code listing for the entire insertEvent method please go view it or download the source from the gitHub repository. It is a standard binary search for an insertion point. To minimize computation, a check is done before doing the binary search. If the trigger time of the event being added is less than the first event’s trigger time the event is prepended. If it is greater than the last event’s trigger time the event is appended. If it is somewhere in-between the binary search process is executed. See the source from gitHub to for the full implementation of the binary insertion algorithm.

One part of the implementation is interesting. To avoid the array copy problem explained in a previous post, the engine’s list properties are modified directly rather than trough a facade-like approach.

isFuture ? futures.insert(an, atIndex: midIndex) 
         : presents.insert(an, atIndex: midIndex)

This line of code is longer and less expressive than I would like it to be but it does avoid the copy problem.

There is some sample code in the ViewController class that shows the engine’s API being used. In it a TraditionalEngine is instantiated and stored as a parameter of the ViewController. 0 is used as the start time of the simulation so all event triggerTimes are considered to be time offsets. In viewDidLoad 50 random integers from 0 – 100 are created and if any of them are a multiple of 15 they are made negative. This will exercise the code handling the situation where the simulation has events to process from before the beginning of the simulation.

class ViewController: UIViewController {
    let theEngine = TraditionalEngine(startTime:0)
                            
    override func viewDidLoad() {
        super.viewDidLoad()
        
        for index in 0..50{
            var randNum = Int(arc4random() % 100)
            if randNum % 15 == 0 {
                randNum = -randNum
            }
            let capturedNum = Int(arc4random() % 50)
            theEngine.addEvent(Event(aTriggerTime: randNum, anAction: {
                println("triggered at: \(randNum) with 
                                   captured: \(capturedNum)")
                }))
        }
        theEngine.go()
    }
}

I’ve used a closure as the action for the events. I chose a closure to show how a constant or variable could be captured and used later when the event’s action is triggered.

All in all, Swift worked quite well for creating a traditionally designed simulation engine.

Swift, facades, and Objects with Collection Type Properties

Posted in iPhone development, mac development tagged , , , , at 7:26 pm by tetontech

Facade functions are very common in software. One of reason to use them is to put common code in a single function but have it behave differently without needing to pass one or more extra parameter indicating which behavior to execute. In Swift this can be problematic if we forget that Arrays, if passed to functions or methods, are copied if something is added to or removed from the passed Array.

Here is an example that separates negative numbers from zero and positive numbers. I have called the class DoesNotWork1 because it doesn’t work in Swift. The negativeInts and positiveInts arrays will always be empty. This is because the Arrays were passed to the _storeInt method.

import Foundation

class DoesNotWork1{
    var negativeInts:Array<Int> = Array<Int>()
    var positiveInts:Array<Int> = Array<Int>()
    
    func storeInt(an:Int){
        if an < 0{
            _storeInt(an, list:negativeInts)
        }
        else{
            _storeInt(an, list:positiveInts)
        }
    }
    func _storeInt(an:Int, var list:Array){
        list.append(an)
    }
}

 

OK … lets try another approach. It is less common that the previous example but is also frequently used. I have named this variation DoesNotWork2. This one doesn’t work for the same underlying reason that DoesNotWork1 fails. The Arrays are getting copied. Why? Because operators in Swift are functions. The arrays passed to the ternary operator ( ? : ) will be copied as soon as we try to modify their length.

import Foundation

class DoesNotWork2{
    var negativeInts:Array<Int> = Array<Int>()
    var positiveInts:Array<Int> = Array<Int>()
    
    func storeInt(an:Int){
        _storeInt(an, isNegative:an < 0)
    }
    func _storeInt(an:Int, isNegative:Bool){
        var list = isNegative ? negativeInts : positiveInts
        list.append(an)
    }
}

What then could a programmer do to create a facade that modifies specific arrays depending on the situation? I’ve called this example DoesWork. The difference is what happens in the ternary ( ? : ) operator. Instead of selecting and returning one of the class’s arrays it modifies them directly.

import Foundation

class DoesWork{
    var negativeInts:Array<Int> = Array<Int>()
    var positiveInts:Array<Int> = Array<Int>()
    
    func storeInt(an:Int){
        _storeInt(an, isNegative:an < 0)
    }
    func _storeInt(an:Int, isNegative:Bool){
        isNegative ? negativeInts.append(an) : positiveInts.append(an)
    }
}

 

June 17, 2014

Swift, Pipelining, Function Arrays, and Operator Overloading

Posted in Uncategorized tagged , , , , , , , at 9:46 pm by tetontech

In a previous post I showed how to create a pipeline operator, |>, that allows chaining of functions, closures, and mixtures of functions and closures. This posting will overload the pipeline operator so it can be used in a related but different situation.

In functional programming there are known good patterns. Two of these are map and reduce. Reduce applies a single function to an array of values and returns a single value. Summing the values in an array of Ints would be a good example.

Map is similar. It also applies a single function to an array of values. It returns a new array containing one value for each value in the original array but the new array values have been modified by applying the function. An example would be to map a double process to the array [1,2,3] generating and returning the new array [2,4,6].

There is yet another pattern that is common in programming and I use it a lot . It is related to map and reduce. In this situation a single piece of data, be it a Dictionary, Array, Int, String, or any other type, is passed to a series of functions. I haven’t seen a specific name for this type of behavior so I refer to it as spindle (a play on words – fold, spindle, or mutilate).

An example situation that fits the spindle pattern is the validation and application of data received from a source such as a file, a server, the user, etc. In this example I’ll be doing something that is so common in programming that it can seem trivial; validating a user name and password, authenticating the user, and displaying the user interface appropriate for the user. To do this let’s pretend that the data to be validated has come to us as JSON and been converted into a Swift Dictionary having the structure ["uName":,"pWord":,"userRole":].

A few functions to apply in our example would be helpful. These consist of different portions of the validation, authentication, display process. In each function a Tuple is returned consisting of a Dictionary<String,AnyObject> and a String? (String optional) (see my previous post for an explanation of using AnyObject with Dictionaries). The String? is used by the overloaded pipeline operator for error detection and early process termination. The example functions are:

func checkUName(data:Dictionary<String, AnyObject>) 
              -> (Dictionary<String,AnyObject>, String?){  
    if let userNameOptional = data["userName"]? as? String{
            if countElements(userNameOptional.stringByTrimmingCharactersInSet(
                   NSCharacterSet.whitespaceAndNewlineCharacterSet())) > 0{
                return (data, nil)
            }
    }
    return (data, "missing user name")
}
        
func checkPWord(data:Dictionary<String,AnyObject>) 
            -> (Dictionary<String,AnyObject>, String?){
    if let passWordOptional = data["passWord"]? as? String{
        if countElements(passWordOptional.stringByTrimmingCharactersInSet(
                  NSCharacterSet.whitespaceAndNewlineCharacterSet())) > 0{
            return (data, nil)
        }
    }
    return (data, "missing password")
}
      
//var data declares the data Dictionary to be variable rather than fixed.
//This is still functional since data is a copy of 
//the original data Dictionary.  
func isUser(var data:Dictionary<String,AnyObject>) 
             -> (Dictionary<String,AnyObject>, String?){
    // place authentication code here.
    /*
    if authentication passes 
          return (data, nil)
          data["isLoggedIn"] = true
    else
    */
    return (data, "invalid user name or password")
}
        
func showRoleDisplay(data:Dictionary<String,AnyObject>) 
              -> (Dictionary<String,AnyObject>, String?){
    // based on data["userRole"] show a view that matches the users role.
    return (data, nil)
}

For this example we create an Array called login that represents the entire process by listing the functions in the order we want them executed.

var login = [checkUName, checkPWord, isUser, showRoleDisplay];

A Dictionary for use in our example is also created.

var user:Dictionary<String,AnyObject> = ["userName":"sue", 
                        "passWord":"gr4583rt!", "userRole":14]

Using the pipeline operator we will see below, the code to apply login to the user Dictionary is

let (aResult, errorMessage) = login|>user

This line of code reads “Let a tuple be assigned the result of attempting to login a user.” You could also think of it as “Apply login to user and assign the result to a Tuple.” Either way you view the line of code, it seems to read well due to the operator.

So what does the code for the overloaded pipeline operator, |>, look like?

Since we declared the operator in a previous post and are using the same project we do not need to redeclare the operator. The code to overload it is

1 func |> <T>(left: Array<(T) -> (T, String?)>, var right: T ) -> (T, String?){
2    for function in left{
3        let (partialResult,message) = function(right)
4        if message != nil{
5            return (partialResult, message)
6        }
7        right = partialResult
8    }
9    return (right, nil)
10}

Operators are functions so the first line includes the func keyword, the name of the operator, two parameters, and a return of a tuple that includes a String optional. The first parameter, left, is an Array of functions that accept any type T and return a Tuple consisting of that type T and a String optional. The second operator, right, is a variable of the same type T.

Line 2 of the operator iterates over each of the functions in the left parameter. Each function is then called on line 3 and its returned result is checked on line 4. If an error message has been received it, along with the object of type T, partialResult, is returned to break the loop and early terminate the execution of the array of functions.

Line 7 updates the result that will be passed to any subsequent functions called or returned as part of line 9.

This operator can also be used with closures since functions are named closures in Swift.

Swift Arrays and Dictionaries with Various Types of Values using AnyObject

Posted in iPhone development, mac development tagged , , , , , at 7:25 pm by tetontech

Apple’s Swift documentation declares that Arrays and Dictionaries can only hold one type of value per collection. This is true but Apple’s examples are a little misleading. The code

var stArr:Array<String> = ["bob","sue"]

does create an Array named stArr that holds only strings. If you tried to add a number to stArr the code would fail to compile. The code

var anotherStrArr = ["sally","joe"]

would also create an Array that can only hold strings. An Array that can only hold Ints would be created from the code

var intArr = [4,56,7,12]

Whether the type is declared, as in the first example, or is the result of interpolation, as in the second and third example, only one type is storable in each of these Arrays.

What is not explained in Apple’s documentation is the use of AnyObject. The code

var interestingArray:Array<AnyObject> = ["sally", "jones", 45]

is not only legal, but it compiles and runs. Why?

Because all of the values in the array of of type AnyObject. An Array of AnyObjects can also be created by the interpolator.

var interpolatedInterestingArray = ["sally""jones", 45]

interestingArray and interpolatedInterestingArray will be identical in type and values. Understanding this isn’t particularly helpful if we restrict ourselves to Arrays. It can be very helpful when Dictionaries are being used. The code

var aPersonDictionary:<String,AnyObject> = ["firstName":"sally", "lastName":"jones", "age":45]

is completely legal, creates a Swift Dictionary, and works well because all key-value pairs are of the same type: <String,AnyObject>. WARNING! The code

var interpolatedPersonDictionary = ["firstName":"sally""lastName":"jones""age":45]

doesn’t yield the same result. Instead, the interpolator will assign a NSDictionary to the variable interpolatedPersonDictionary rather than a Swift Dictionary. This is important to know if you have a function that expects a Swift Dictionary. You can not directly pass an NSDictionary as a Swift Dictionary. They are not the same type.

My next post contains an operator and functions that need a Swift Dictionary using AnyObject rather than an interpolated NSDictionary.

June 13, 2014

Swift, WKWebView, and Calling from Swift to Javascript

Posted in Uncategorized tagged , , , , at 7:34 pm by tetontech

In a previous post, I showed how to embed Apple’s new WKWebView using Swift to create a ‘full view’, hybrid JavaScript application. An ability that QC Hybrid and PhoneGap, both early hybrid development platforms, had was to allow calls to be made from Javascript down to the native language of the device. In the case of iOS that was, and can still be, Objective-C but now can also be done in Swift. The new WKWebView has new functionality available in both languages that requires much less overhead to accomplish this interoperability than the old iOS UIWebView and Android WebView. The WKWebView currently does have an important limitation I’ll discuss in a moment.

There are two parts needed to achieve iOS’s new interoperability; a ‘listener’ of type WKScriptMessageHandler on the Swift side and a new object that has a postMessage() method on the Javascript side. When the Javascript postMessage() method is passed an array, associative array, object, or other Javascript type, the postMessage() method will JSON what it was passed. It then pushes this JSON string as a message to a queue on the Swift side of the application. At this point the JSON is parsed and the message becomes the matching Swift types, Array, Dictionary, String, Int, Double, etc. Custom Javascript objects become Dictionaries. Now your code in the WKScriptMessageHandler’s didRecieveMessage() method has Swift objects without needing to use JSON libraries in either the Javascript or Swift portions of your code. This is great. Unfortunately, at the time of this posting, there is no matching functionality in the beta release to easily push Swift objects back up to Javascript. Hopefully this will come soon. If not, there will need to be some ‘hack-like’ work-arounds similar to what QC Hybrid and PhoneGap had to do. This would be unfortunate.

The source code for this posting’s example is a modification of the previous post’s source. Rather than repeat the discussion of those portions of the example I’d suggest you review the previous post about how to do the embedding. The example below is the contents of a ViewController.swift file. It includes the changes needed to setup JS -> Swift interoperability (JS->Objective-C would use the same classes and methods) for an iOS single view application. The changes can be seen in lines 4, 14-18, and 29 – 31.

Line 4 declares the ViewController class as conforming to the WKScriptMessageHandler protocol. Notice that unlike Objective-C, Swift protocol declarations look just like object inheritance calls (in this case ViewController inherits from UIViewController). Swift only allows single inheritance, like Java. When doing both inheritance and protocol declarations the inheritance declaration must come first. If no inheritance is being done then a protocol declaration can be the first item after the : operator.

1 import UIKit
2 import WebKit
3
4 class ViewController: UIViewController, WKScriptMessageHandler {
5    
6    override func viewDidLoad() {
7        super.viewDidLoad()
8        
9        //prepare
10        var path = NSBundle.mainBundle().pathForResource("index", 
                                        ofType: ".html")
11        var url = NSURL(fileURLWithPath:path)
12        var request = NSURLRequest(URL:url)
13        
14        //changes from last post
15        var theConfiguration = WKWebViewConfiguration()
16        theConfiguration.userContentController.addScriptMessageHandler(self, 
                                        name: "interOp")
17        var theWebView = WKWebView(frame:self.view.frame, 
                                        configuration: theConfiguration)
18        //end of changes
19        
20        theWebView.loadRequest(request)
21        self.view.addSubview(theWebView)
22    }
23
24    override func didReceiveMemoryWarning() {
25        super.didReceiveMemoryWarning()
26        // Dispose of any resources that can be recreated.
27    }
28    
29    func userContentController(userContentController: WKUserContentController!, didReceiveScriptMessage message: WKScriptMessage!){
30        println("got message: \(message.body)")
31    }
32
33 }

Line 15 introduces a new class, WKWebViewConfiguration. This class manages various types of configurations for any and all WKWebViews used in your applications. One of the WKWebViewConfiguration’s properties is a content controller named userContentController. This is the object we need to access in order to setup the ViewController class as the ‘listener’ for messages from Javascript.

Line 16 shows how to assign the ViewController to be the Javascript message handler for any messages generated as part of the named message queue ‘interOp’. You can select any name you want instead of interOp. It just sounded good to me.

Line 17 shows how to initialize the WKWebView with both a frame and the WKWebViewConfiguration instance. This tells the WKWebView to create an opportunity to use the Javascript postMessage() method.

We’re almost done. The only other change needed is to create the ‘listener’ method, userContentController.didRecieveScriptMessage(). One of the parameters to this method will be the WKScriptMessage generated as part of the interoperation between your JavaScript and Swift. The message has a property named body that is the Swift version of the JSON data passed from JavaScript. Line 30 shows this example printing the Swift objects that the example sends from the Javascript side.

I created a simple Javascript function in the project’s main.js file that you can see below. Notice the new window.webkit.messageHandlers object. It has an attribute ‘interOp’ that matches the name we used on line 16 of the Swift code. The JavaScript interOp object is the ViewController since it conforms to the WKScriptMessageHandler protocol and was assigned on line 16 with the interOp name.

function sendMessage(){
    var aMessage = {'command':'hello', data:[5,6,7,8,9]}
    window.webkit.messageHandlers.interOp.postMessage(aMessage)
}

That’s it. Now we can send any object, array, or primitive as a message to Swift. Hopefully Google will not re-invent the wheel when they add this same type of interoperability to Android. They should make their Javascript side look exactly this same way. There is some advantage to copying.

 

For an example of how to call from JavaScript to Swift and then back to JavaScript see this other post.

Next page

Follow

Get every new post delivered to your Inbox.

Join 318 other followers

%d bloggers like this: