Category: iOS

A couple of days ago I decided that a good way to show my maths for graphics skills would be to produce an app that allows graphing of polygons. This wouldn’t be possible without understanding how to measure the size of the screen, and to control the drawing of points, lines and fills. So far I haven’t added the transformation matrices, but that won’t actually be as difficult as what I’ve done so far.

The first thing I did was learn how to override the draw function of the UIView class. A good introduction to this topic can be found on AppCoda, which suggests creating a custom UIView subclass called DemoView. In this class, the draw function is overridden to run functions that draw shapes using UIBezierPath objects. My class is called GraphArea and I based my polygon on their createTriangle() function, but added three more points.

Each point in the polygon obviously has an X and a Y value, so my control panel needed to have a UIStepper to control each value, and a UITextField to display them all. In my main ViewController file, I created outlets actions for my 12 steppers. Within their actions, the steppers run a function that basically takes all the stepper values and passes it to the GraphArea instance. Once the polygon was being displayed properly, I thought it would be useful to also draw a circle at each point so they’re easier to track. Once I did this, I thought it would be even better if all 6 points were colour coded, and these colours were matched by the control panel so you knew which point you were moving.

I added the ability to maximise the graph area so that you can get a better look at the shape. This involves changing the constant of the constraint that positions the control panel (which has a fixed height) against the bottom of the screen to a negative value equal to its height. I used UIView.animate to make the change a smooth sliding motion and, since the GraphArea is within a constrained UIScrollView which scales automatically, it has to scale accordingly.

Although the height becomes equal to the ViewController’s height, the width has to scale by the same amount. Otherwise the polygon would only scale in one direction, and stretch instead of ‘zooming in’. It took a while to get this right, but it basically involves increasing the width by the same amount as the height increases.

This is all I have so far. Hopefully the transformation matrices will be as easy to implement as I think they’re going to be. Then I can try to do some 3D graphics, which will obviously involve projecting a 3D cube onto the 2D plane of the phone screen.

When I originally made my Pet Timer app, I made it with one pet in mind. Bunny Timer was my first iOS release, and after a few months I thought I’d create two separate versions. Bunny Timer FREE (back when Apple allowed apps with the word ‘FREE’ in the title) would have basic functionality, while the full paid version of Bunny Timer would have more features and options.

To attract more users who might prefer other users who might prefer another pet, I created Dog Timer and Cat Timer, which both had their own free and a paid version. This left me with a total of six apps with very similar features. I eventually stopped testing each of these six apps for bugs, as I was focusing all my energy on my newer projects.

That’s why I decided to remove all six from the App Store, and do the sensible thing.

I’m creating one unified Pet Timer app for iOS, and I’ll be packing as many of the old featueres into it as I can.

This will be my first iOS app writing C# in what was once Xamarin Studio (now Visual Studio For Mac). Since I created the unified Android version of Pet Timer using this IDE, I should be able to reuse most of the code logic. That was my plan, but almost immediately I ran into a roadblock. Then I ran into another roadblock.

The first roadblock was the Xamarin iOS Designer. While it works perfectly well (provided you have Xcode installed) for dragging and dropping items from the Toolbox, the problem is creating constraints. For whatever reason, my version of Visual Studio didn’t have any way to create constraints other than adding the ‘recommended’ constraints.

After trying and failing to get these to work as needed, I looked on the Xamarin Forums where someone basically said don’t bother using the Xamarin iOS Designer for constraints. Instead they said to use Xcode, which is great because that’s what I’m used to. I created my entire menu UIViewController in Xcode, saved the file and went back to Visual Studio.

That’s when the second, much more difficult roadblock occurred.

I went to ViewController.cs and started typing the name of the label that shows the hours a user has selected. Visual Studio autocompleted the name, showing it was aware of the identifier I had set in Xcode. In ViewDidLoad I wrote a simple delegate that would handle when the user interacted with the UIStepper for hours:

This was a very simple thing to request, and yet when I built and ran the solution, nothing would happen. The UIStepper was aware of its minimum value (zero) as the minus button would grey out when it reached that value. But the label remained unchanged. I searched for a Xamarin or StackOverflow forum to help me, but had no luck.

As seems to happen very often when using Xamarin and Visual Studio, I went for the nuclear option. I created an entirely new Xamarin.iOS project, put a label on it, gave it an identifier, and set its value in ViewDidLoad(). That was successful, which made me think I could just import the old Main.Storyboard I created in Xcode and have that work, too.

I was mistaken.

However, I had the idea to delete the last character of the identifier, changing ‘hoursLabel’ to ‘hoursLabe’, and saving Main.Storyboard. Lo and behold, this identifier would autocomplete in ViewController.cs, and would respond to UIStepper changes by the user. I had to do this for all identifiers, and then change their names back to their original names.

TL;DR: Xamarin iOS Designer isn’t great for creating constraints and sometimes you’ve got to modify identifiers just so they’ll respond to basic events!