Tuesday, October 6, 2015

Getting started with iOS Development- No more XML

Well, I finally am making the plunge. After weeks of postponing, delays, justification and just general laziness I pulled myself together and started the iOS side of development. For those that don't know me I have always had a preference to Android (or an irrational dislike of Apple and its products) so my desire to work on iOS definitely came with a bias against it.

That being said, as a developer with a background in .NET, C#, WPF and Android moving to iOS can be TOUGH. It is a very different paradigm shift to move from xml based UI development, which I have really grown to love, to iOS Storyboards, which still confuse me. Storyboards are built with a visual flow to them, this gives you a nice ability to get a good overview of the app and how it navigates but the individual details are not as easy to manage. Additionally, coming from a world of Layout Controls, moving to the paradigm of Auto-Layout and Constraints can also be a unique challenge. Overall the shift for me hearkens back to a day of WinForms development. It is definitely something new for me.

Much as before, this will likely see a few iterations as my knowledge grows. I decided to follow a similar pattern to how I built my Android UI, first loading the main character overview page, then start building it out from there. So after setting up my initial UI I found myself with this general starting point:

I'll deal with layout later.
The first challenge I ran into was a new paradigm for my drop down selection boxes. Where android has a spinner control that provides a drop down list for you to interact with, that is not something available on iOS.

They have a picker control instead, which is described as using "a spinning-wheel or slot-machine metaphor to show one or more sets of values". If you notice, I am using Text Field's for my data display since there was no "combo box". After some research I learned that iOS actaully has a pretty cool solution set up for something like this. What i needed to do was wire the Text Field input option to be a Picker control instead of the default keyboard input. iOS, in this regard, actually makes this quite simple to do. Text Fields, and many other controls, have a property called InputView which defines what control is the selected input. Keyboard is the default when nothing is set, so instead I set it to a created Picker Control, like so:

var racePicker = new UIPickerView (CGRect.Empty);
racePickerText.InputView = racePicker;

Then a picker control is displayed when we click the Text Field like so:


Overall this is a good start. Different from what we had before, but it works. This does bring up a couple more questions however, populating our data, binding it to the Text Field itself, and then dismissing our Picker when we are done.

1. Setting up the Data.
This is an area that is actually not as documented in Xamarin, but is something that needs to be learned. In Objective-C/Swift world the UIPickerView has two main sources for data and interaction. The Delegate and DataSource. The DataSource is, as you can guess, the data that is tied to the control. You can think of Delegates kind of like the controller layer, defining interaction. 

In Xamarin, both of these properties are exposed, as well as a hybrid Object called the UIPickerViewModel. This is something specific to Xamarin, but basically serves as a hybrid of the two previously mentioned properties and is more C# styled. I learned, over time, that this is a paradigm we do quite frequently but it is something we admittedly do not have as much documentation on. For the case of my application it served my needs. Knowing I had at least four different scenarios I wanted a data source for my object, I created a general PickerModel and overrode the defined methods to use my data, and then set my model in my picker control:

var model = new MyPickerModel (RaceHelper.GetAllRaces (), info.Race.Name);
model.OnPropertySelected += (object sender, EventArgs args) =>  

{
    racePickerText.Text = model.SelectedItem;
};
racePicker.Model = model;


The constructor is how I set my initial conditions, and then if you notice I have a defined PropertySelected event so that I can feedback to my UI when items are updated. Then I was able to get my data populating within my UIPickerView:
The final piece to the puzzle was dismissing the view. This took a bit of hunting and research and then I finally found the final piece. Along with an InputView, there is also an InputAccessoryView. This gives you the ability to add a toolbar to your InputView, giving additional functionality and methods of interaction, including a "Done" button in my case. Setup was actually pretty simple:

var toolbar = new UIToolbar (new RectangleF (0.0f, 0.0f, 50.0f, 44.0f));
var myButton = new UIBarButtonItem (UIBarButtonSystemItem.Done,

     delegate {
          this.racePickerText.ResignFirstResponder (); 

     });

toolbar.Items = new UIBarButtonItem[] {

     new UIBarButtonItem (UIBarButtonSystemItem.FlexibleSpace), myButton };

racePickerText.InputAccessoryView = toolbar;

And what this gives us is the final product here:


Next step will be to organize the code to be more clean/refactored but that will be for another time.


Again I apologize for lack of diligence in getting things posted, lots going on but hopefully I will get updates on a more regular pace once more as I dig into the world of iOS.

No comments:

Post a Comment