Reactive Cocoa (CIDUG meeting, September 25, 2012)

Josh Abernathy of GitHub gave a presentation on the Reactive Cocoa framework last night at the CIDUG meeting. His way of describing the framework was a way to encapsulate and perform operations on a sequence of values over time. His UI demo using the framework was interesting, it was a bit hard to wrap the brain around in a quick demo setting, I would have to look at it again to try to understand and digest how it works and is beneficial over standard ways of doing UI operations.

BTW, today is the anniversary of the passing of Shawn Lane, who was an immensely talented guitar player. Any time you are feeling low, keep in mind that there are people who have gone through worse.

The app delegate’s UIWindow is finicky

I learned the hard way that there is a right way to do things in your didFinishLaunchingWithOptions with regards to self.window, and then there is the way that Apple used to have apps work that does not work any longer.

In case you haven’t heard, screen rotation in iOS 6 is much different from the previous versions of iOS. As a result, I was banging my head against the wall trying to figure out the magic incantation to get my rotation working again, and as it turned out, it had to do with this line of code in my app delegate:

[self.window addSubview:navigationController.view];

I was building my UINavigationController in the code and assigning it to the window as shown above. On the advice of an enterprising Stack Overflow user, I changed the line of code to this:

[self.window setRootViewController:navigationController];

And now the rotation events are starting to once again fire in my app. Yay.

For some additional information on how iOS6 handles rotation differently, please visit this blog post, which is where I found part of the information that I needed to get rotation working again in my app:

iOS 6 SupportedOrientations with UINavigationController – Shabbir’s Code Snippets

BTW, Happy Anniversary to Devil’s Tower, which was declared to be the first National Monument in the U.S. on this date in 1906. I now have a burning desire to watch Close Encounters for about the 100th time.

How to dynamically generate a TrackBallInfoTemplate

The Telerik ChartView control is nice, but if you cannot create your XAML ahead of time (or in other words, you don’t know how many LineSeries you are going to have on your chart), then you are in uncharted territory. Especially if you are not super solid in WPF and data binding as I am.

Using their example code, I was able to get the track ball info to show the date and value of the data points (basically the X and Y values of the data point), but instead I wanted to show a label for that LineSeries along with the Y value. Initially I tried to use a DataTemplate in the Resources of my user control, but I could not get the binding to work the way I wanted to.

Finally, to solve this issue, I had to resort to build the XAML in my code and set the TrackBallInfoTemplate. Here is what it looks like:

// the class holding the data for the chart...
public class SalesInfo
    public string Employee { get; set; }
    public DateTime Time { get; set; }
    public int Value { get; set; }

// then, further on down the code...
Color[] colorArray = { Colors.Red, Colors.Green, Colors.Blue, Colors.Yellow };

// and...
data = new RadObservableCollection(data.OrderBy(x => x.Time));
Color dataColor = colorArray[loopCounter % 4];
LineSeries line = new LineSeries();
line.Stroke = new SolidColorBrush(dataColor);
line.StrokeThickness = 2;
line.CategoryBinding = new PropertyNameDataPointBinding() { PropertyName = "Time" };
line.ValueBinding = new PropertyNameDataPointBinding() { PropertyName = "Value" };
line.ItemsSource = data;

StringBuilder templateString = new StringBuilder();
templateString.Append("<DataTemplate xmlns=''>");
templateString.Append("<StackPanel Orientation='Horizontal'>");
templateString.Append("<TextBlock Text='" + u + "' />");  // u refers to the name of this line series (Employee)
templateString.Append("<TextBlock Text=': ' />");
templateString.Append("<TextBlock Text='{Binding DataPoint.Value}' />");

var xml = XmlReader.Create(new StringReader(templateString.ToString()));
var tbiTemplate = (DataTemplate)XamlReader.Load(xml) as DataTemplate;
line.TrackBallInfoTemplate = tbiTemplate;

And so now, here is what my chart view looks like with the customized track ball info:

BTW, Happy Birthday to Ty Tabor.

EDIT: I would like to take a moment to say thanks to Yavor from Telerik, he responded to my posting on the Telerik forums and pointed out that the DataPoint object has a DataItem object child that is the object that created the DataPoint. As a result, in my XAML Resources, I can bind to DataPoint.DataItem.Employee, and it works as expected. Here is that link:

Creating LineSeries programmatically with custom TrackBallInfoTemplate

Intermittently localized strings (and MobileVLC build issues)

So I was having an issue with my NSLocalizedString entries. At seemingly random intervals, the app that I built and deployed to either the simulator or the iPad would display the key that I pass into NSLocalizedString instead of the value from my Localizable.strings file. Which is very annoying.

As it turns out, the app was getting confused because I had 2 Localizable.strings files in my project. So if this is happening to you, make sure that you are looking at the file list in your workspace, and start typing Localizable in the search field at the bottom of the list. If you see more than two Localizable.strings files, consolidate them into one and then delete the extra ones.

Also, I have been having a devil of a time trying to get MobileVLC built and running. If you can help, please take a look at my posting on Stack Overflow on the latest issue:

iOS SDK 5.1 linker error for non_lazy_ptr in Xcode 4.4.1

I have also posted to the VideoLAN forum about this issue, again with no luck:

iOS SDK 5.1 linker error for non_lazy_ptr in Xcode 4.4.1

BTW, happy birthday (posthumously) to Danny Gatton, a supremely talented guitar player who left us too soon.