Stephen Smith's Blog

Musings on Machine Learning…

Posts Tagged ‘iOS

UI Testing in Swift

with one comment

Introduction

To round out my blog series on an introduction to Swift, this posting will be covering UI Testing. Previously we created a simple Swift program to draw a Koch Snowflake, adding some unit tests and then added some performance tests.

The source code for the project is on Google Drive here.

UI Testing actually runs the program like an end user would run the program and if you switch to the simulator while the test is running you can watch these actions take place. Unlike many other UI testing frameworks, this one just interacts with the screen controls, if done properly there is no code involving doing things at specific (x,y) co-ordinates. The magic that makes this work is the iOS accessibility layer that was created to help people with disabilities use Apple products. For instance, the VoiceOver feature that reads the screen needs to interact with the controls in the same way as our UI Tests.

This then means that UI Tests also provide a good means for testing some of the accessibility aspects of our iOS applications. Fully supporting accessibility is an often neglected area and really deserves more consideration. The great thing here is that by making your UI Tests thorough you are also validating that many accessibility technologies will also work.

UI Testing in XCode

When you create a new Swift project in XCode and select unit testing you also get a skeletal group for UI Tests with some setup and a dummy test. You create you test by selecting an empty (or not) test and then pressing record and then manually perform the tests. When you close the simulator a bunch of recorded code will be pasted into your project. This then is a great starting point for writing more thorough tests. You then use all the same XCTAssert type functions as in the unit testing framework to check for problems.

Screen Shot 2016-06-15 at 8.41.45 AM

Gotchas

Not Having Accessibility Setup Correctly

If you haven’t set an accessibility identifier for your control, you won’t get the correct code recorded. Recording will try its best, but it will give you something that probably won’t work. This happened to me. I kept the bad code from the first attempt in the file commented out so you can see it. Generally, if the accessibility is setup right, the code is simple complete and will work. If not, you will find things you did not recorded and other things having hardware or synchronicity problems (strange errors which if you google have workarounds but it all becomes quite complicated).

Screen Shot 2016-06-15 at 8.42.06 AM

Keyboards and other Hardware

I performed my tests on my MacBook which of course has a fixed keyboard. When recording tests, make sure you use the iOS keyboard (that is on the screen). Generally, you want the tests to use all the iOS stuff and not the macOS stuff which makes using the simulator easier. Another approach is to access text fields via the clipboard using cut/paste so as to avoid the keyboard entirely. I tend to think for a good UI test you should test all the cases, but perhaps not on every text field. Also beware text already in text boxes that may need to be cleared first. One way to do this (probably the best way) is to add a clear button in the text boxes properties and then press this. In the recorded sample I hit the delete key a couple of times. Note that tapping a field usually doesn’t select all the text.

Synchronization

Beware that if you cause something to popup or be created, chances are your test code will run faster than that and start using things before they are created. You will need to add wait loops to wait for controls to exist before using them. This case doesn’t happen in the Koch snowflake program. Generally, you don’t want to insert sleep type statements to wait a couple of seconds, this slows down your UI tests and can prove unreliable and lead to investigating a lot of false failed tests. Always better to look for specific events and to proceed quickly.

The Test

The code for the test is below. The setUp and teardown methods were generated by XCode and I didn’t change them. The code for the testExample routine was generated by recording, then I just cleaned up a bit of noise. The intent is that it sets fractal level to 3 and then to 4. If you click on the simulator while running, then you can see this happen. Unfortunately, there isn’t really a good way to validate that it works correctly, so this is really only a run without crashing sort of test, unless you manually observe it.

//
//  KochSnowFlakeUITests.swift
//  KochSnowFlakeUITests
//
//  Created by Stephen Smith on 2016-05-13.
//  Copyright © 2016 Stephen Smith. All rights reserved.
//

import XCTest

class KochSnowFlakeUITests: XCTestCase {

    override func setUp() {
        super.setUp()

        // Put setup code here. This method is called before the invocation of each
        // test method in the class.
        // In UI tests it is usually best to stop immediately when a failure occurs.

        continueAfterFailure = false

        // UI tests must launch the application that they test.
        //Doing this in setup will make sure it happens for each test method.
        XCUIApplication().launch()

        // In UI tests it’s important to set the initial state -
        // such as interface orientation - required for your tests before they run.
        // The setUp method is a good place to do this.
    }

    override func tearDown() {
        // Put teardown code here. This method is called after the invocation of
        // each test method in the class.
        super.tearDown()
    }

    func testExample() {

        let app = XCUIApplication()
        app.textFields["textField"].tap()

        let deleteKey = app.keys["delete"]
        deleteKey.tap()
        deleteKey.tap()
        app.textFields["textField"].typeText("3")

        let returnButton = app.buttons["Return"]
        returnButton.tap()

        deleteKey.tap()
        deleteKey.tap()
        app.textFields["textField"].typeText("4")
        returnButton.tap()
    }
}

Summary

The UI testing support built into XCode and Swift is quite nice. Certainly comparable to some quite expensive packages available in the Windows world. Since iOS and macOS are quite a controlled environment and the accessibility support is quite good, this makes this package quite nice. The main thing to watch out for is the proliferation of Apple hardware to check. It appears that going forwards Apple is spending quite a bit of time ensuring automated testing works quite well for their development platform.

Advertisements

Written by smist08

June 15, 2016 at 4:09 pm

Posted in Mobility, programming

Tagged with , , ,

Adding Unit Tests to My Swift Application

with 3 comments

Introduction

Last time I blogged on creating my first Swift application that would display a Koch Snowflake fractal on an iPad or and iPhone. This time I’m going to look at adding some unit tests to that program to see how that works in XCode and Swift. It appears that Apple has built some nice unit testing support into XCode so doing this was actually quite easy.

I put the Koch Snowflake Swift project on Google Drive here. Feel free to download it and play with it. Refer to this project or the previous blog post for the code we are actually testing in this article.

Test Driven Development

If I was following proper Test Driven Development (TDD) then I should have written the unit tests before I wrote the actual code. This would force me to think about the design of the APIs and the testability of the program first, and then would force quick cycles of writing tests, writing code so the tests pass and then refactoring the code to make it all better. However, in this case I ported an old Objective-C program to Swift to play with Swift and now that I’m getting more familiar with Swift, I’m finally looking at the unit testing framework. So what I’m doing is perhaps not a good practice, but adding the unit tests later is better than not adding them at all.

The danger I could have run into is that the program could have turned out to be quite hard to test due to perhaps some bad design decisions and then required quite a bit of refactoring to make it properly unit testable. Fortunately, in this case the program is fairly simple and adding a good set of unit tests was fairly straight forward and didn’t require any changes to the program.

One criticism of TDD is that there is a perception that it interferes with good program design and architecture. This isn’t true. The misconception is that the first tests need to be truly useful, whereas the first tests usually just call the API and set how the API to the various classes is used. The classes are just skeletons and the unit tests pass as long as everything compiles. Getting everything to compile is the first step and thinking about all the APIs before writing the real code that does stuff is the first step to getting a good modular design.

Apple has adopted TDD for a lot of their own projects, for instance their Core Data module was developed this way. Since Apple developers use XCode and now many are using TDD this means that a lot of good support for TDD is being baked into XCode. It also means that newer Apple technologies are much easier to use in a TDD environment than some of their older ones. But even for the older ones there are lots of clever examples on the web of how to work around the various challenges they introduce.

Screen Shot 2016-05-31 at 10.41.21 AM

Testing Turtle Graphics

When you create a project with XCode you have the option to include unit tests (which I did) and this gives you a test project that you can run with some dummy tests in it. So I figured first let’s add some unit tests to my TurtleGraphics class. This is pretty simple you move the turtle and turn the turtle and it leaves a trail behind it. For drawing fractals turtle graphics makes the algorithms very easy since it fits in well with the recursive algorithms typically used.

The turtle graphics class uses Apple’s Quartz2D library to draw on the screen. Perhaps the first possible design flaw is that when I instantiate the turtle graphics library I need to pass its constructor a valid graphics context. The underlying Quartz2D library routines certainly don’t like this being nil and throw an exception if you try that (ie my first try). So I thought I would just create a graphic context object but after battling with Swift a bit, I found I couldn’t do this because the underlying class doesn’t have any constructors. This also prevented me from mocking the class (at least using the real class and replacing just a few methods). This is because Apple wants to make sure you get a valid graphics context from one of their factory methods. If you are actually in the drawing routine this is passed to you by the system, but as a unit test, we aren’t running in a screen drawing context. Fortunately there is a way to get a graphics context to draw on an in-memory image file, so I used that.

To solve this, I could have refactored the drawing routines into another class and had this class accept nil for the graphics context and just return when this happens. This is basically just making a new class that pass through to the real class when the program runs, or acts as a stub class when running unit tests. I didn’t like this so much since then if the real program did pass nil, it wouldn’t get caught and the program just wouldn’t work properly. Even though I’m not testing the actual placement of pixels on the screen, it makes me feel good to know the actual real drawing routines are being exercised during the unit tests, so if they do get an invalid argument or something the problem will be caught.

The unit test framework lets unit tests get at variables in a class to help you set up the asserts to prove correctness (you import the module via @testable import KochSnowFlake rather than just import), so to test it, I just did some simple move and turns and then tested that the internal state of the turtle graphics module was correct. Notice when I turned 45 degrees I used trigonometry to calculate the new position, for testing its usually good to test against a calculation, rather than running the program to see what the value is and then using that. Notice the use of XCTAssertEqualWithAccuracy, since we are using floating point arithmetic, rounding errors creep in, so the equals will never be exact. You can configure XCode to either stop on each error or run to completion just recording all the errors, its up to you. For this I usually just stopped on an error and then fixed the problem.

func testTurtleGraphics() {
 // Test the turtle graphics library.
 // Note we need a valid graphics context to do this.
 
 UIGraphicsBeginImageContextWithOptions(CGSize(width: 50, height: 50), false, 20);
 let context = UIGraphicsGetCurrentContext();
 let tg = TurtleGraphics(inContext: context!);
 XCTAssert(tg.x == 50, "Initial X value should be 50");
 XCTAssertEqual(tg.y, 150, "Initial Y value should be 150");
 XCTAssertEqual(tg.angle, 0, "Initial angle should be 0");
 tg.move(10);
 XCTAssertEqual(tg.x, 60, "X should be incremented to 60");
 XCTAssertEqual(tg.y, 150, "Initial Y value should be 150");
 XCTAssertEqual(tg.angle, 0, "Initial angle should be 0");
 tg.turn(90);
 tg.move(10);
 XCTAssertEqualWithAccuracy(tg.x, 60, accuracy: 0.0001, "X should be o 60");
 XCTAssertEqualWithAccuracy(tg.y, 160, accuracy: 0.0001, "Initial Y value should be 160");
 XCTAssertEqual(tg.angle, 90, "Initial angle should be 90");
 tg.turn(-45);
 tg.move(10);
 XCTAssertEqualWithAccuracy(tg.x, 60 + 10 * sqrt(2) / 2, accuracy: 0.0001, "X should be o 60+10*sqrt(2)/2");
 XCTAssertEqualWithAccuracy(tg.y, 160 + 10 * sqrt(2) / 2, accuracy: 0.0001, "Initial Y value should be 160+10*sqrt(2)/2");
 XCTAssertEqual(tg.angle, 45, "Initial angle should be 45");
 
 UIGraphicsEndImageContext();
 
 }

Testing the View Controller

Now let’s test things at a higher level. Generally, we don’t do UI testing in unit tests, but we can do some basic tests to ensure everything is created properly and is more or less hooked up correctly. XCode does have built in support for UI testing and perhaps we’ll have a look at that in a later blog post. In this case we are going to create the storyboard (where the UI is defined) and from that instantiate our View Controller. Then we do a dummy access for the view to get the delay loaded elements loaded and start calling the View Controllers methods starting with viewDidLoad(). For our test we set the fractal level to 3 in the text box and then call the notification methods and see if it then updated properly in our View.

func testInitialViewController()
 {
 // Test that the storyboard is connected to the view controller and
 // that we can create and use the view and controls.
 
 let storyboard = UIStoryboard(name: "Main", bundle: nil)
 
 let viewController = storyboard.instantiateInitialViewController() as! ViewController
 _ = viewController.view
 viewController.viewDidLoad()
 
 viewController.fractalLevelTextField.text = "3"
 viewController.textChangeNot("dummy")
 XCTAssertTrue(viewController.fracView.level == 3)
 // This next line is just to get 100% code coverage.
 viewController.didReceiveMemoryWarning()
 }

Test Coverage

The big questions that is usually asked about unit tests, is how much code to they cover (or exercise). XCode can give this report which you can see in the screenshot:

Screen Shot 2016-05-31 at 10.42.53 AM

Amazingly we nearly get 100% coverage. The only module with poor coverage is AppDelegate.swift which is code generated by XCode and then I never use it. The reason we get such good coverage is that this is a fairly simple program and it draws the snowflake when it initializes. But the key point here is that I am testing a lot of things fairly easily and fairly quickly. It tests the functionality of the turtle graphics library and it tests that the UI is all hooked up properly and working.

A true TDD adherent would delete all the code in AppDelegate.swift, since code shouldn’t be written unless it is to make a unit test pass. But I tend to give an exception to code generated by the tools like XCode, to me this code is Apple’s responsibility and not mine. Plus, if I ever do add code to this class then I would need to start adding unit tests and take it a bit more seriously.

Harder Cases

This program is pretty simple, so I didn’t need to do anything too fancy to unit test it. This is mainly because there is no database access, no hardware access (beyond drawing and one text field) and no communication with a server. If you add these then you would need to add mock, stub and/or fake classes to assist in testing. You want your unit tests to be fast and run on every compile. You don’t want to require databases be setup or that servers are running somewhere in a certain state. Fortunately, Swift is a very powerful object oriented language and creating all of these is fairly easy (extensions are especially helpful). The main problems you run into are in using the Objective-C libraries like UIKit, but again you aren’t the first to run into these and there are tons of sample code, blogs and lessons on how to deal with these.

Another tricky area is with asynchronous calls. When you make a call to the server, the response will be returned asynchronously. What this means that as soon as your unit test sends the server request, it will complete. Since the asynchronous request comes back on a separate thread later, you need to ensure your main thread doesn’t just end and you wait for the results, or the tests in the callback will never be executed. There are lots of examples on how to do this, but it definitely adds some complexity to your tests.

Continuous Build Server

If you have a team, then you will probably want a continuous build server that monitors your source code repository (probably Git) and then does a build and test each time something new is checked in. Apple has an XCode Server that you can purchase if you are a registered developer. Or you could use the Jenkins Build Server which is open source and free. Jenkins also has an XCode plugin to make life a bit easier. Though XCode is quite good at letting you control it from the command line. This way you can be notified as soon as something breaks and ensure problems get fixed right when they are caused, which is the easiest time to fix them.

Summary

That turned out to be quite a long posting on unit tests. XCode and Swift have a very powerful and easy to work with unit testing framework built in. If you are developing a new application, certainly consider using TDD for your development methodology. If you are porting or doing a new version of an app, then certainly try adding some unit tests. Unit tests will help you greatly over the lifetime of your product, making it more reliable, bug free and easier to maintain.

Written by smist08

May 31, 2016 at 8:17 pm

My First Swift Application

with 3 comments

Introduction

Back in 2013 I purchased a MacBook Air, installed XCode and wrote a small Objective-C program to draw a simple fractal on an iPad. Which I then blogged on here. Now we are a few years later and I thought I would give Apple’s new programming language Swift a try and see how iOS/OSX development has evolved as a result. For more details on Koch snowflakes and what I the program does, check out my original article.

The Evolution from Objective-C to Swift

Objective-C was one of the first object oriented extensions to the C Programming language. Its first main usage was by Steve Jobs and NeXT Computer as the primary programming language of the NeXTStep operating system which later became OS/X and iOS. Objective-C had a lot of innovative ideas behind it like treating everything as sending messages between objects (rather than directly calling methods). But then C++ came along and became the main standard for an object oriented extension to C.

One of the complaints against C is that it puts a lot of burden on programmers since they are dealing with memory and the computer architecture at a very low level. You are manipulating memory pointers directly, allocating memory buffers, etc. This is all very powerful and produces very fast, compact and efficient programs. But there is a lot of room for error, since making a mistake here will lead to buffer overruns, program crashes and such. In the days of standalone computers this was annoying but not fatal. Now with the internet, these sorts of problems lead to security vulnerabilities and server crashes. All that being said, if you have skilled programmers, C, Objective C and C++ are very powerful and you can produce great reliable programs with them.

To address these problems, Sun Microsystems invented Java. Java was essentially an object oriented extension of C, but with all the pointers and low level memory access removed. Java then included a large standard class library to give an alternate way of doing all the low level things you did in C. Java compiled to P-Code which ran on a Java Virtual Machine. This could then be sandboxed to allow greater security. To some degree this was to try to reach a compromise between scripting languages like JavaScript or VBScript and true fully compiled languages like C++. I.e. to make it easier to program with less gotchas, but still maintain the compiler checks for correctness and modules features required to program large systems.

Microsoft saw the potential and growing success of Java and came up with their own competing system namely C#. C# was initially very similar to Java with a very similar class library. Microsoft actually originally had their own implementation of Java, but it really sucked and it was easier to move true Java programs to C# than it was to Microsoft Java. Similar to the Java VM, C# runs on Microsoft’s .Net framework which isolates you from the underlying operating system.

Java got off to a great start, but as Sun workstations went into decline, Sun couldn’t put the necessary R&D resources into supporting Java and forward progress slowed. Oracle bought Sun and took over Java, but Oracle doesn’t seem to be putting much effort into Java, besides suing the various users of it like Google.

Microsoft has been doing a lot of good work developing C# and has been putting a lot of work to evolving the language and evolving the .Net framework. Certainly modern C# has come a long way and contains a lot of powerful modern object oriented features that weren’t present initially and aren’t present in Java.

A couple of years ago Apple finally noticed this trend and produced their own modern object oriented language namely Swift. Swift isn’t a true object oriented extension to C, the core language has a lot of differences to C. Some things are quite similar like building expressions, but other things are quite different, like how you define variables. Swift has all the modern object oriented features like closures, extensions, generics, etc. which you would expect. Further since a lot of the language was re-imagined over C, it has a lot of nice built in features like ranges. If you look at just the core language, its quite clean, powerful and modern.

There are quite a few blog posts comparing these various languages such as these two articles on C# vs Swift: C# vs Swift and C# vs Swift. If you Google, there are a lot of discussions on the various points of these languages. Often the discussions also consider Go and Python.

Frameworks

The ugliness in all these safe modern languages comes in with how they interact with the underlying operating system. Neither Apple nor Microsoft re-wrote their operating systems to be safe and natively support these. At some point you have the transition from the nice safe, clean object oriented world into the old pointer based C world. Microsoft with the underlying Windows DLLs and Apple with the Objective-C based application frameworks and then to the underlying Unix based operating system kernel.

Sun took the highest approach making its own frameworks for everything and then leaving it to the JVM implementation on each system to translate native to this, so to a Java programmer everything looks the same. This sounds great, but doesn’t work well in practice since it doesn’t give you access to all the operating system features and makes your program less competitive. This resulted in the development of JNI and Java programs natively calling through to the ugly world outside the JVM.

Microsoft built the .Net framework on top of Windows, which provides most things you need and has been filling in more and more. But you still often need to call native DLLs directly (which makes you application unsafe).

Apple decided to use the current iOS/OSX frameworks directly and allowed Swift to interact bi-directionally with Objective-C libraries. This then allowed Swift programmers to directly leverage their knowledge of UIKit for instance to write programs. The downside of this is that it puts a lot of ugly code directly in your nice clean Swift program to deal with these older frameworks.

Koch Snowflakes Revisited

I ported my Objective-C Koch Snowflake program from 2013 over to Swift. This turned out to be pretty straight forward. I think the program source code is much cleaner once moved over to Swift and I definitely prefer Swift to Objective-C for programming. Since I’ve been doing mostly C# programming the past few years, it fells much more natural to me than Objective-C.

Although most of the code is cleaner, you can see a bit of ugliness around the interactions with the UIKit framework. I especially don’t like using the types their rather than the native Swift data types.

Screen Shot 2016-05-16 at 9.46.04 AM

Other Development Notes

For the UI, I used the standard storyboard screen designer which is shared by both Objective-C and Swift. Like most systems that edit your code, you just need to be careful not to edit the code inserted by the UI designer or they get out of sync and produce weird errors. I changed a variable name generated by the UI designer and it was a bit of a head scratcher tracing back from the error message to what was wrong.

I created the project as a standard single page application and set it to run on both an iPhone and iPad. There are now 12 standard devices of various iPad and iPhone models directly supported, I tried a couple of them, but certainly didn’t test with each one.

Generally, when you make a project you can create any new class in either Swift or Objective-C and have them interoperate. So you can bring in older code rather than porting it.

The debugger is quite nice, its easy to step through your code and see what is going on. Generally, XCode is a very powerful development platform and has a lot of great tools to support you in your programming. I haven’t added any unit tests yet, but I plan to have a look at the testing framework next and perhaps that will be the topic of a future blog.

Screen Shot 2016-05-16 at 9.44.39 AM

Summary

I think Swift is a huge improvement for programming iOS and OS/X over Objective-C.  Although Swift is open source and can be run on Linux, the Apple UI frameworks like UIKit are not open source. So I don’t think Swift will be any help in developing cross platform programs (unless they are very simple command line utilities). Swift is quite a modern language and its object oriented implementation is quite nice. Apple seems to be putting quite a bit of effort into Swift with version 3 of the language soon to be released. There is certainly a large community of iOS developers out there who should be putting it to good use.

This was a fun little project and I think I will be spending a bit more time dabbling is iOS development using Swift.

Source Code Listings

//
//  ViewController.swift
//  KochSnowFlake
//
//  Created by Stephen Smith on 2016-05-13.
//  Copyright © 2016 Stephen Smith. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    // MARK: Properties
    @IBOutlet weak var fractalLevelTextField: UITextField!
    @IBOutlet weak var fracView: FractalView!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        //

        fractalLevelTextField.text = "2";
        fracView.level = 2;

        NSNotificationCenter.defaultCenter().addObserver(self,
               selector: #selector(textChangeNot),
               name: UITextFieldTextDidChangeNotification, object: fractalLevelTextField);
    }

    func textChangeNot( object: AnyObject )
    {
        if let enteredLevel = NSNumberFormatter().numberFromString(fractalLevelTextField.text!)
        {
            fracView.level = Int(enteredLevel);
            fracView.setNeedsDisplay();
        }
    }

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

//
//  FractalView.swift
//  KochSnowFlake
//
//  Created by Stephen Smith on 2016-05-13.
//  Copyright © 2016 Stephen Smith. All rights reserved.
//

import UIKit
class FractalView: UIView {
    var level = 1;

    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect) {
        var frac: KochFlake;

        // Drawing code

        let currentColor = UIColor.blackColor();
        let context = UIGraphicsGetCurrentContext()
        frac = KochFlake(inContext: context!);

        //Set the width of the "pen" that will be used for drawing
        CGContextSetLineWidth(context,1);

        //Set the color of the pen to be used
        CGContextSetStrokeColorWithColor(context, currentColor.CGColor);

        frac.KockSnowflake(level);

        //Apply our stroke settings to the line.
        CGContextStrokePath(context);

    }
}

//
//  KochFlake.swift
//  KochSnowFlake
//
//  Created by Stephen Smith on 2016-05-13.
//  Copyright © 2016 Stephen Smith. All rights reserved.
//

import UIKit

class KochFlake
{
    var tg:TurtleGraphics;
    var context:CGContextRef;

    init(inContext: CGContextRef)
    {
        context = inContext;
        tg = TurtleGraphics(inContext: context);
    }

    func KockSnowflake(level:Int)
    {
        tg.turn( 60 );
        KockSnowflakeSide( level , size:400);
        tg.turn( -120 );
        KockSnowflakeSide( level, size: 400);
        tg.turn( -120 );
        KockSnowflakeSide( level, size: 400);
    }

    func KockSnowflakeSide(level:Int, size:Int)
    {
        if (level == 0)
        {
            tg.move( size );
        }
        else
        {
            KockSnowflakeSide( level - 1, size: size / 3 );
            tg.turn( 60 );
            KockSnowflakeSide( level-1, size: size / 3);
            tg.turn( -120 );
            KockSnowflakeSide( level-1, size: size / 3);
            tg.turn(60);
            KockSnowflakeSide( level-1, size: size / 3);
        }
    }
}

//
//  TurtleGraphics.swift
//  KochSnowFlake
//
//  Created by Stephen Smith on 2016-05-13.
//  Copyright © 2016 Stephen Smith. All rights reserved.
//

import UIKit
let pi:CGFloat = 3.14159;

class TurtleGraphics
{
    var x, y: CGFloat;
    var angle: CGFloat;
    var context: CGContextRef;

    init(inContext: CGContextRef)
    {
        context = inContext;
        x = 50.0;
        y = 150.0;
        CGContextMoveToPoint(context, x, y);
        angle = 0.0;
    }

    func move( dist: Int )
    {
        x = x + CGFloat(dist) * cos( angle * pi / 180.0);
        y = y + CGFloat(dist) * sin( angle * pi / 180.0);

        CGContextAddLineToPoint(context, x, y);
    }

    func turn( angleIncrement: Int)
    {
        angle = angle + CGFloat(angleIncrement);
    }
}

 

Written by smist08

May 16, 2016 at 8:00 pm

Apple Mobile Trends

with 2 comments

Introduction

With Apple’s WWDC conference just wrapping up, I thought it might be a good time to meditate on a few of the current trends in the mobile world. I think the patent wars are sorting themselves out as Google and Apple settle and we are seeing a lot more competitive copying. Apple added a lot of features that competitors have had for a while as well as adding a few innovations unique to Apple.

The competitive fervor being shown in both the Google and Apple mobile camps is impressive and making it very hard for any other system to keep up.

ios8_large

Cloud Storage

Apple has had the iCloud for a while now, but with this version we are really seeing Apple leverage this. When Google introduced the Chromebook they used this video to show the power of keeping things in the Web. This idea has been copied somewhat by Microsoft. But now Apple has taken this to the next level by allowing you to continue from device to device seamlessly, so you can easily start an e-mail on your phone and then continue working on it on your MacBook. No having to e-mail things to yourself, it all just seamlessly works.

Apple also copied some ideas from Google Drive and DropBox to allow copying files across non-Apple devices like Windows as well as sharing documents between applications. So now this is all a bit more seamless. It’s amazing how much free cloud storage you can get by having Google, Microsoft, Apple and Dropbox accounts.

Generally this is just the beginning as companies figure out neat things they can do when your data is in the cloud. If you are worried about privacy or the NSA reading your documents, you might try a different solution, but for many things the convenience of this outweighs the worries. Perhaps a bigger worry than the FBI or NSA is how advertisers will be allowed to use all this data to target you. Apple has added some features to really enable mobile advertising, whether these become too intrusive and annoying has yet to be seen.

Copying is the Best Compliment

Apple has also copied quite a few ideas from Google, Blackberry and Microsoft into the new iOS. There is a lot more use of transparency (like introduced in Windows Vista). There is now a customizable and predictive keyboard adding ideas from Blackberry and Microsoft. Keyboard entry has been one of Apple’s weaknesses that it is trying to address. Similarly the drive option in the iCloud is rather late to the game.

Apps versus the Web

There is a continuing battle between native applications and web applications for accessing web sites. People often complain that the native mobile application only gives them a subset of what is available on the full web site, but then on the other hand the consensus is that the native mobile apps give a much better experience.

True web applications give a unified experience across all devices and give the same functionality and the same interaction models. This is also easier for developers since you only need to develop once.

However Apple is having a lot of success with apps. Generally people seem to find things easier in the Apple App store than in browsing and bookmarking the web. Apple claims that over half of mobile Internet traffic is through iOS apps now (but I’m not sure if this is skewed by streaming video apps like Netflix that use a disproportionate amount of bandwidth).

Yet another Programming Language

Apple also unveiled a new programming language Swift for mobile development. One of the problems with C, C++ and Objective C programming is the use of pointers which tends to make programming harder than it needs to be. Java was an alternative object oriented extension to C with no pointers, then C# came along copying much of Java. Generally most scripting languages like Basic, JavaScript, Python, etc. have never had pointers.

Rather than go down the road of Java and C#, Swift has tried to incorporate the ease of use of scripting languages, but still give you full control over the iOS API. How this all works out is yet to be seen, but it will be interesting if it makes iPhones and iPads really easy to program similar to the early PCs back in the Basic days.

swift-screenshot

The Internet of Things

Apple introduced two new initiatives, their Health Kit and Home Kit. Health kit is mostly to encourage adding medical sensing devices to your iPhone, whereas Home Kit is to extend iOS into devices around the home and to control them all from your iPhone.

The Health Kit is designed to centralize all your health related information in one central place. There is getting to be quite a catalog of sensors and apps to continuously track your location, speed, heart rate, pulse, blood pressure, etc. If you are an athlete, this is great information on your fitness level and how you are doing. Garmin really pioneered this with their GPS watches with attached heart rate monitors. I have a Garmin watch and it provides a tremendous amount of information when I run or cycle. I don’t think this is much use for the iPhone, which I always leave behind since I don’t want to risk it getting wet, but this might really take off if Apple really releases a smart watch this fall like all the rumors say.

Home Kit is a bit of reaction to Google buying Nest, the intelligent thermostat. Basically you can control all your household items from your phone, so you can warm up the house as you are driving home, or turn all the lights on and off remotely. We have a cottage with in-floor heating, it would be nice if we could remotely tell the house to start heating up in the winter a few hours before we arrive, right now it’s a bit cold when we first get there and turn on the heat. However with zoned heating we would need four thermostats and at $250 each, this is rather excessively expensive. I think the price of these devices has to come down quite a bit to create some real adoption.

There is a lot of concern about having all of these hacked and interfered with, but if they get the security and privacy correct, then these are really handy things to have.

Summary

Apple has introduced some quite intriguing new directions. Can Swift become the Basic programming languages for mobile devices? Will Health Kit and Home Kit usher in a wave of new wonderful intelligent devices? Will all the new refinements in iOS really help users have an even better mobile experience? Will native apps continue to displace web sites, or will web sites re-emerge as the dominant on-line experience? Lots of questions to be answered over the next few months, but it should be fun playing with tall these new toys.

Written by smist08

June 7, 2014 at 4:27 pm

Sage Mobile Service

with 22 comments

Introduction

Last year at Sage Summit we showed proof of concept demos of a number of mobile applications we were developing. At this year’s Sage Summit we announced that these were now shipping. In this blog posting, I’m going to talk about one of these new mobile applications, namely Sage Mobile Service. This application dispatches technicians to perform work for customers and enables them to get directions, customer information and to collect payments.

Common users of this service would be plumbers or electricians. Where calls come into a dispatch center and they need to be scheduled to visit various sites. There they perform work and can collect payments. Hopefully any companies that perform work of this nature will find this App helpful.

This application consists of three parts: a web application to manage customers and dispatch work orders, an iPhone application for technicians to receive information and take payments and then a connection to your on premise ERP system to share transactions and data.

The Dispatch Web Site

The Dispatch Web Site is a standard web application that runs in any modern browser. From this website you can manage your customers and create work orders for your technicians to perform. Below is the welcome/dashboard home page for this website.

service2

You can get lists of the current work orders along with lists of your customers and drill down into the detailed information of anything listed.

service3

When a call comes in from a customer, perhaps for a plumbing problem, you can enter in all the information and then schedule a technician to perform the work.

service1

As soon as the work order is saved with an assigned technician and scheduled time, it will be available on his iPhone so he can go do the work.

The iPhone App

The technician receives these service call requests from their iPhone via an App. This App lets them know where they should be and when. The App will present a schedule of the work they need to perform today, tomorrow and in the future. This gives the technician an idea of all the work they have to do today and how long they have been scheduled to perform that work. Below is a screen shot of a work order on an iPhone, you can scroll down for more information or tap to drill down for more detailed information.

service5

They can also get additional information on the customer, like their location, directions and contact people. They can also bring up a history of service calls for that customer so they know ahead of time what work has been performed previously.

service4

From the App they can also add work items and parts. So if they need to add their billable hours or add any chargeable parts then they can do this.

When the work is completed, the technician can either receive payment via swiping a credit card through a device attached to their iPhone or they can mark it on account. Of course all sales taxes will be calculated automatically as part of this process. If it’s on account then an invoice will be sent later. Next week I’ll talk about the Sage Billing and Payments web application which can be used to collect these invoices if they aren’t paid on time.

Connected to ERP

Where do the customers come from? Where do the payments made go? The answer is your on premise ERP system. A small connector is installed onto your on premise ERP system which is configured to communicate with your Sage cloud account. This connector will upload information from your ERP like your list of customers to the cloud and will download transactions as they are completed to the ERP. Initially we have connectors for Sage 100 ERP and Sage 300 ERP. We will have connectors for Sage 50 ERP (US and Canada) following shortly.

cloudconnector

In the case of Sage Mobile Service all the customer information along with information required to fill out A/R Invoices is uploaded to the cloud and then A/R Invoices are downloaded and inserted into the ERP as transactions are processed in the cloud or on the mobile devices. The connectors for Sage 100 ERP and Sage 300 ERP run continuously as a Windows service and need to be installed on a server that is generally running. The Sage 50 ERP connectors are part of the product and need to be run manually every now and again.

All the requests are queued, so if one system or another is down, things will catch up again once it is available. The connectors only call up to the cloud, the cloud never calls down to the ERP. This means you don’t need to operate a web server and you don’t need to reconfigure your firewall. Installation is very easy and transparent.

International

Initially we have been rolling this out in North America. We will be rolling this out internationally, but first we have to provide the sales tax calculation engine (currently we use Avalara) and we need to provide integration to local credit card processors. Depending on the region, it might make sense to roll out the service, perhaps without credit card support, but this will be on a case by case basis. Fortunately most regions have simpler VAT type sales taxes rather than the crazy US system.

Summary

The world of mobile applications is opening up all sorts of new opportunities to expand ERP systems from beyond hidden backroom offices out into the real world. No one wants to have to enter data twice, so these applications are great mechanisms to get transactions entered directly into the ERP from the point of work and not relying on paper records that are later typed in (perhaps inaccurately). Sage Service Billing is one of our first wave of these applications with more to follow.

Written by smist08

August 10, 2013 at 7:26 pm

Google Forks WebKit

with one comment

Introduction

WebKit is the underlying HTML rendering library used primarily by the Apple Safari and Google Chrome browsers. It is used in a lot of other projects like the Blackberry Browser, Opera, Tizen, Kindle and even some Microsoft e-mail clients. Even Nokia was a big WebKit user before switching to Windows Phone. Generally it’s been considered a great success, rallying the web around standards and making life easier for web developers.

webkit

WebKit is a solid open source project with lots of support. This is one reason it’s so successful. Currently in Internet browsers there are three main HTML rendering engines: the Internet Explorer Trident engine, the Mozilla Firefox Gecko engine and then WebKit.

The big news around the Internet on this front recently is that Google is forking WebKit (meaning starting a new open source project based on WebKit) and then taking it in its own direction with a project called Blink. This raises all sorts of questions: like what it means to web developers? What is Google’s real agenda? Will this damage web standards? Will this slow WebKit development? In this blog posting I want to give my perspective on a few of these questions.

History

Actually WebKit was started out of a similar controversy. Back in 2001, Apple forked the KHTML/KJS HTML rendering engine used by the browser that is part of the KDE Linux User Interface system. Basically Apple wanted something better and more tuned for its OS X project. The result was the Safari browser built on the first WebKit HTML engine. At the time no one in the Linux community was happy about this, but in the end looking back, success makes everything all right.

So now that Google is forking WebKit, claiming that it’s for the same reasons that Apple forked KHTML, will history repeat itself and a much better HTML rendering engine will emerge? Or will this just fragment the market into more slightly different HTML rendering engines making life more difficult for web developers?

WebKit’s Mobile Success

In recent years, now that Android and the iPhone have completely taken over the mobile phone market, developing web sites with HTML5 and JavaScript has become much easier. This is because WebKit is used in both of these families of devices. This means to cover 95% of the mobile market you just need to target WebKit. This greatly simplifies development and testing. Further WebKit follows web standards diligently, it keeps up with evolving standards, has great performance and great quality.

I think that WebKit has been a major contributor to the combined success of both Android and the iPhone. You can easily browse most websites from these devices. Plus when Apps incorporate browser controls they are using WebKit.

Further both Apple and Google are contributing actively to WebKit. It’s been an interesting combination of co-operation and competition. When new hardware devices come out, initially it tends only be accessible for Apps. But Google tends to very quickly add JavaScript APIs for the device to WebKit. Then Apple tends to follow suite quite quickly. Further each is driven to keep incorporating the latest version into their devices since they don’t want to let the other get ahead of them.

One of the worries of Google forking WebKit and going its own way is that we will lose the competitive nature of Apple versus Google that has been driving WebKit forwards.

Why Fork?

So why is Google forking WebKit? A lot of opinion on the Internet is that this is a strategy to sabotage Apple. I guess Google could be egomaniacal enough to think that WebKit will fail without them participating. But Apple is such a big company with so much money and talent, I think they can do just fine with WebKit, after all they did start it without Google’s help. Further I suspect the army of independent open source programmers that contribute to WebKit will continue to do so and won’t switch to Blink.

Google’s official reason is that the code in WebKit is getting too burdened with supporting code for Safari, Chrome and all the other various things it does. That if they take WebKit and remove anything that Chrome doesn’t use then they will have a smaller, faster and easier to develop code base. Basically they claim they want to move the HTML engine forwards more tightly coupled with their multi-processor architecture to improve security and performance. That doing this while supporting competing architectures within the same code base is getting harder and harder.

When Apple started WebKit and later when Google joined it, both Google and Apple were primarily worried about Microsoft and wanted to have Browser technology clearly superior to Internet Explorer. Now with their success, Microsoft is now pretty well non-existent in the mobile world. I think as a result Google isn’t feeling threatened by Microsoft anymore and is turning its attention to Apple. Generally relations between the two companies have been getting colder and colder in recent years.

Actually Google currently only uses the HTML and CSS rendering part of WebKit called WebKitCore. They stopped using the JavaScript component JavaScriptCore in favor of their own V8 JavaScript engine. The V8 JavaScript engine has been blowing away the competition in JavaScript benchmarks for some time now. In fact the V8 JavaScript engine is also the heart of Node.js the highly successful JavaScript server side processing framework. I think Google is looking to get the same sort of success out of Blink that they got from V8.

What’s the Problem?

The problem is for developers. Right now developing good web pages that run nicely anywhere means targeting IE, FireFox and WebKit which then covers the main HTML/CSS rendering engines. Unfortunately HTML and CSS are very complicated and quite subtle. Although all adhere to the published web standards, there are differences in interpretation. Also there are emergent properties that get exploited as features, things that aren’t really in the standard but have appeared in an implementation.

In the mobile world right now, developers have it easier since they can target Android, iOS, Blackberry, Tizen and Symbian by just targeting WebKit. This makes life much easier since you really can develop once and deploy pretty much anywhere. It will be a pity to lose this, and potentially quite expensive for smaller development organizations.

I imagine that many source code files will continue to be shared by WebKit and Blink. But for how long? When will we have to pay attention between differences between Blink based browsers and WebKit based browsers?

Summary

Although I find it appealing that Google is hoping to do for HTML/CSS rendering speed what it did for JavaScript execution speed with V8, I’m really worried that this is going to fragment HTML5 development for mobile devices. I tend to think this will cause more web developers to decide that if I need to develop Android and iOS separately then I may as well do both natively in Apps. To me this will be a sad further fragmentation and polarization of mobile developer communities.

Written by smist08

April 13, 2013 at 3:40 pm

My First Experience Writing an iPad App

with 2 comments

Introduction

To get a feel for iOS programming I thought I would create a simple iOS application to display a Koch snowflake. There would be a simple edit box where you enter the fractal level and then it will draw the snowflake. I thought this would be a good example to get a feel for the XCode development environment, simple user interaction with controls and a flavor for some graphics programming.

Two jobs before I started with Computer Associates to work on CA-Accpac/2000, I worked for a company that created stock market software. They were working on a new workstation version for the NeXT computer. So with that company (over 20 years ago), I gathered good experience in this environment. We programmed in Objective-C and used the innovative NeXTStep development environment which had many neat features like using DisplayPostScript for rending on-screen graphics.

Now so many years later, here I am programming iOS and relearning Objective C. Although Apple has had many battles with Adobe over the years resulting in display postscript never being mentioned, I still see it there in how you do things. Since I’m newly relearning all this stuff and there have been many changes in the past 25 years, don’t take everything I say as the best way to do things, they are the way I first figured out how to do things for this simple project. Especially if you can do something visually in XCode versus writing code, I probably wrote code because that’s what I’m most comfortable with.

XCode

XCode is Apple’s IDE for doing both native Mac OS and IOs development. XCode is a very rich development environment with many built in tools for things like unit testing, debugging, screen designing and such. It has built in support for the Git source code control system, which is used by default for all projects. There is much built in documentation and help, as well as emulators to test and debug your iPad and iPhone applications. The main requirement of XCode is that it runs on MacOS. Hence I have to run it on my trusty MacBook Air.

XCode has a great many productivity helpers like auto-complete and many way to graphically create your programs rather than coding them. The thing that gave me the most trouble was the graphical part, I’m fine with writing code, but graphically connecting things wasn’t as intuitive to me as I would have expected.

xcode

Koch Snowflakes

Koch snowflakes are simple fractals that are a good way to give an idea of how fractals can build complexity out of simplicity. Basically you start with a base shape, in this case a triangle, then you replace each line segment with a new shape, in this case the two lines with a “v” in the middle. Then you do this recursively to get more and more complicated shapes. Below is the progression from level 0, the base shape to level 1, with the base shape lines replaced by the fractal generator and then so on as the level increases.

koch-snowflake-progression

This is a fractal because in the limit as the level goes to infinity, the shape has a fractal dimension, in that it is somewhere between 1 dimensional and 2 dimensional in a defined mathematical sense.

Turtle Graphics

To me the easiest way to draw fractals is with a turtle graphics library. This is a simple drawing library where you tell a turtle to either turn or move forwards. As he moves he leaves a trail. Hence the base shape for the Koch snowflake is forward 1, turn 60, forward 1, turn -120, forward 1, turn 60 forward 1. This is then really easy to apply recursively to draw fractals.

Objective C

Objective-C was one of the first object oriented extensions to C. It was implemented as a pre-processor that generated C code which was then compiled using regular C development tools. This greatly simplified implementation, but the syntax reflects that it was designed to be easily processed by a preprocessor. It’s certainly evolved since its early days, but is perhaps considered a bit clunky as a result. Objective-C has all the object oriented features like inheritance and classes, but lacks a lot of the complexity of C++. The object oriented features are more similar to Java, but unlike Java, Objective-C still has all of C under it, meaning all the pointers and pointer related features that Java removed; hence you can easily crash your iOS app if you make pointer mistakes like in a C program.

Both Java and C++ overloaded the pointer syntax to call methods and such making them behave like function pointers in a structure. Objective C tried for a syntax to reflect message passing using their square bracket syntax of [object method] to send a message to an object. See the source code listings below for some examples. Recently Objective C has adopted the pointer type syntax as an option but considers it good coding practice to only use this for accessing class properties.

My iPad App

When you create a new project in XCode you get a complete working program and then only have to fill in your own code for your functionality. I edited the iPad storyboard to have a single page consisting of a label and text field for the fractal level and then a view to draw the image on. I created a couple of classes, one for turtle graphics, another to draw the fractal and then one to act as the interface to the UI form. All in all, not a lot of code and it seems to run fairly well. I placed the source code listings at the end so as not to clutter up this article. Beware that WordPress often changes characters for typographic reason, things like regular double quotes to 66 or 99 type quotes, this tends to introduce syntax errors if you cut and paste the code, so beware.

Storyboards are a relatively new feature to XCode, they allow you to define many screens within a single file and to connect them all together, so a button on one screen can trigger a transition to another screen, all setup graphically with no code. This is a great tool for quickly prototyping applications, but since for this app, I only have one screen it isn’t really used.

To connect the controls in the storyboard to the code, you create matching variables in the generated interface file and then drag an arrow from a small o in the margin to the matching control in the storyboard file (a process I find a bit cumbersome). Then you can ask for notifications and set properties for the various controls. You can see a couple of examples in the interface file below.

With any object oriented framework like Cocoa Touch there is quite a steep learning curve. Not only do you need to find the properties and methods to call to do things for you, but you also need to learn when you have to extend one of the system base classes. In the case of drawing the fractal, it’s a matter of putting a view control on the page, but then you need to extend the default class to override its drawRect method that is called whenever the view need redrawing. This is similar to handling a WM_PAINT message in Windows. Again you can have a look at the code down below.

Below are a couple of screen grabs of running this iPad app in the iPad emulator on my MacBook Air:

level2

 

level4

Summary

Sadly you can’t just post and distribute iPad apps, but have to go through the Apple iTunes store. I’m not going to bother posting this app, so you can’t play with it. I do like being able to post source and app to let people just run it, but Apple doesn’t allow this.

Creating this app was fun. XCode is quite a good development environment and they make it easy to write code quickly. iOS is a very full featured operating system with many built in services and a great deal of power. This are tons of books and internet articles on iOS development along with all the Apple documentations. Now to dig in a bit deeper to what you can do.

Source Code Listings

//
//  csFractal.m

//  Fractal1
//
//  Created by Stephen Smith on 2013-03-05.
//  Copyright (c) 2013 Stephen Smith. All rights reserved.
//

#import "csFractal.h"
#import "csTurtleGraphics.h"

@implementation csFractal
{
    csTurtleGraphics *tg;
    CGContextRef context;
}

- (id)initWithContext: (CGContextRef) inContext
{
    self = [super init];
    if (self)
    {
        context = inContext;
        tg = [[csTurtleGraphics alloc] initWithContext:context];
    }
    return self;
}

- (void) KockSnowflake:(int)level
{
    [tg turn: 60];
    [self KockSnowflakeSide: level size: 500];
    [tg turn: -120];
    [self KockSnowflakeSide: level size: 500];
    [tg turn: -120];
    [self KockSnowflakeSide: level size: 500];
}

- (void) KockSnowflakeSide: (int)level size:(double) size
{
    if (level == 0)
    {
        [tg move: size];
    }
    else
    {
        [self KockSnowflakeSide: level-1 size: size/3];
        [tg turn: 60];
        [self KockSnowflakeSide: level-1 size: size/3];
        [tg turn: -120];
        [self KockSnowflakeSide: level-1 size: size/3];
        [tg turn:60];
        [self KockSnowflakeSide: level-1 size: size/3];
    }
}

@end

//
//  csTurtleGraphics.m
//  Fractal1
//
//  Created by Stephen Smith on 2013-02-23.
//  Copyright (c) 2013 Stephen Smith. All rights reserved.
//

#import "csTurtleGraphics.h"

const double pi = 3.14159;

@implementation csTurtleGraphics
{
    double x, y;
    double angle;
    CGContextRef    context;
}

- (id)initWithContext: (CGContextRef) inContext
{
    self = [super init];
    if (self)
    {
        context = inContext;
        x = 50.0;
        y = 150.0;
        CGContextMoveToPoint(context, x, y);

        angle = 0.0;
    }
    return self;
}

- (void)move:(int) dist
{
    x = x + dist * cos( angle * pi/ 180.0);
    y = y + dist * sin( angle * pi/ 180.0);
    CGContextAddLineToPoint(context, x, y);

}

- (void) turn: (int) angleIncrement
{
    angle = angle +angleIncrement;
}
@end

//
//  csViewController.m
//  Fractal1
//
//  Created by Stephen Smith on 2013-02-10.
//  Copyright (c) 2013 Stephen Smith. All rights reserved.
//

#import "csViewController.h"

@implementation csViewController

@synthesize textField;
@synthesize fracView;

- (void)viewDidLoad
{
    [super viewDidLoad];
                // Do any additional setup after loading the view, typically from a nib.
    textField.text = @"2";
    [fracView setLevel: 2];

    [[NSNotificationCenter defaultCenter]
        addObserver:self
        selector:@selector(textChangeNot:)
        name:UITextFieldTextDidChangeNotification
        object:textField];

}

- (void) textChangeNot: (id) object
{
    [fracView setLevel: textField.text.intValue];
    [fracView setNeedsDisplay];
}

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

@end

//
//  csFractalView.m
//  Fractal1
//
//  Created by Stephen Smith on 2013-02-17.
//  Copyright (c) 2013 Stephen Smith. All rights reserved.
//

#import "csFractalView.h"
#import "csFractal.h"

@implementation csFractalView
{
    csFractal *frac;
    int level;
}
- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        // Initialization code
        level = 1;
    }
    return self;
}

- (void) setLevel: (int)lev
{
    level = lev;
}

// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
    // Drawing code

    UIColor* currentColor = [UIColor blackColor];
    CGContextRef    context = UIGraphicsGetCurrentContext();

    //Set the width of the "pen" that will be used for drawing
    CGContextSetLineWidth(context,1);
    //Set the color of the pen to be used
    CGContextSetStrokeColorWithColor(context, currentColor.CGColor);

    frac = [[csFractal alloc] initWithContext: context];
    [frac KockSnowflake: level];

    //Apply our stroke settings to the line.
    CGContextStrokePath(context);
}

@end

Written by smist08

March 16, 2013 at 4:59 pm