Review of my Xamarin F# Event Code Leads To Improvements

Not at all surprisingly, it turns out that F# events need not be the crufty structures I showed in my previous post.

First, Xamarin‘s David Siegel suggested “Let the Event type be inferred, don’t define a delegate type, and send simple typed values rather than EventArgs:”


open System

type Control() =
let hello = Event<_>()

member this.Hello = hello.Publish
member this.Speak() = hello.Trigger "yo!"

let control = Control()

control.Hello.Add < | fun msg ->
printfn "Received '%s'" msg

control.Speak()

While Ryan Riley suggested a step further down the reactive line:

To remain consistent with your pipe forwards when using events, you can use the Observable module:
do myItem.FooEvent |> Observable.add (fun o args -> …)
or even
let disposable = myItem.FooEvent |> Observable.subscribe (fun o args -> …)
You can also expose an event as an IObservable rather than as an event if you like:
FooEvent.Publish :> IObservable


I also learned from @kemnet that List.choose id is the idiomatic way to transform a List<option> into a List of Some values.

Review of my first real F# program written in Xamarin

tl;dr: F# has a long learning curve (it takes a long time to master) but productivity happens quickly.


I recently wrote my first real application in F#. Although I’ve been using F# for many of my scripting needs for about a year and use F# to explore iOS APIs regularly, this application is the tool in which I’m going to live for the next several months. As such, I wanted to use a modicum of decent practices: separating UI from behavior and test-driven (or at least test-supported) development. On the other hand, every day I spent writing the app was a day I wasn’t doing the task it was meant to aid, so I needed my programming time to be primarily about implementation, not Functional Purity or pushing the corners of the envelope of my understanding of F#.

The actual project is proprietary, so I can’t be particularly specific nor share code, but it involves a lot of fiddly details surrounding the part that actually requires expertise. Without automation, the fiddly details end up not only taking a significant amount of time in themselves but they prevent me from achieving flow, which I think is an even greater problem for my overall productivity. (Note to self: Write blogpost titled “Work harder, not smarter,” about the importance of achieving flow.)


One of the major aspects of the task involves writing XML. As an example of the type of trade-off that I found easy to make, I mutate the XElements rather than using a Zipper or something like that.

On the other hand, it’s amazing how quickly and constantly mutability bites you in the ass. This is one aspect of functional programming that I do think is a legitimate surprise. Although I believe “prefer immutability to mutability” is just good programming and not a revelation brought down from the mountain by Haskell, when you write code in which most of your identifiers are assignment-only, it highlights how often your troubles rotate around those with a mutable modifier or values that depend on the order in which things are initialized.

On the other other hand, the stringly-typed nature of the world is not to be dismissed. My biggest bug, which lay there for 2 days being passed by my test suite, was an XPath mistake. I also have some regular expressions in the program; these happen to be pretty straightforward, but obviously regexes are another place where the advantages of strong typing are often undermined by convenience.

As Peter Norvig told me during a conversation about type systems and the Mars Climate Orbiter (the one lost due to using the wrong units of measure):

I don’t know of any language, no matter how type-strict, that forces you to tag the string “123.45” in a file with the units of force (newtons vs foot-pounds), nor do I know of any language, no matter how type-loose, in which you could not impose such a convention if you wanted to.


I very much wanted to separate the domain logic from the interface. Since I’m going to be living in this tool for months, there is a definite advantage if I can run it on my iPhone and Nexus 7 as well as my desktop Mac (did I mention that I was writing this using mono?). Since one can write an F# iOS app in 39 lines of code and since cross-platform applications are easy to write with Xamarin, this is straightforward. On the other hand, I needed to make sure that I was correct that the, you know, functionality was worthwhile in the first place.

So I wanted my initial version to be a command-line app. It’s been awhile since I’ve written an input loop and I don’t know if I’ve ever done one with a Model-View-Controller architecture before!

Although I took the Coursera course on Reactive Programming, staying event-driven was another example of letting pragmatics override a learning opportunity (no actors, no reactive extensions… Erik Meijer would be so ashamed of me…). This is one of the few places where F# disappointed me a little. My events look like this:

type EventType = Foo | Bar | Bat

type ParamArgs< 'T>(value : 'T, change : EventType) = 
    inherit System.EventArgs

    member this.Change = change
    member this.Value = value

type ChangeDelegate< 'T> = delegate of obj * ParamArgs< 'T> -> unit

type MyType =
    let fooEvent = new Event<changedelegate <string>, ParamArgs<string>>()

    [<clievent>]
    member this.FooEvent = fooEvent.Publish

And on the receiving side:

do myItem.FooEvent.AddHandler(
    new ChangeDelegate<string>(
        fun sender args -> //handle the event
    )
)

Which, now that I type it out, doesn’t look all that bad. But given how spoiled you get about not spending your time finger-typing in F#, it feels crufty.

As an example of how F# generally spoils you, I offer the “forward pipe operator”:

let baz = foo |> bar |> bat 

Which should bring a nod from anyone familiar with the UNIX shell. It’s the equivalent of, say:

let baz = bat(bar(foo()))
//or
let fooResult = foo()
let barResult = bar(fooResult)
let baz = bat(barResult)

But it’s superior to both those forms. It’s just easier to read than the in-to-out, right-to-left nested function call (putting aside the parentheses, about which more later…). But it’s superior to the second in a more fundamental way. Phil Karlton tells us

There are only two hard things in Computer Science: cache invalidation and naming things. [And off-by-one errors.]

The really nice thing about piping is the way it ties together the expression without intermediate names. The pipes indicate

Here, foo, bar, and bat are logically connected: you can’t replace foo and bar without considering the effect on bat, the calculation of bat is not only tied up with the calculation of bar, it’s also tied up with the calculation of foo. BUT the result of foo and the result of bar aren’t important outside of the calculation of bat! The result of bat is not just used immediately: it has a name and therefore has some importance.

That’s a lot of context to get from a language operator! It’s not just a convenience or a way to avoid a keystroke or two. It’s a good thing that you miss as soon as you work in another language.

Regrettably, I don’t feel as positively about F#’s indentation rules. I’m not going to go into too much detail on this, because I think it’s just a matter of personal preference (I take the increasing ubiquity of Python in the science community as evidence that I’m in the minority…). I can imagine that my irritation might go away with better tooling and some more-understandable compiler errors.


In F#, as with several other functional languages, enclosing function arguments with parentheses is optional: one can say Foo a as opposed to Foo(a). I’m pretty resistant to that: I don’t find Foo a easier to read at all. But the pipe operators (there’s also a backwards pipe) make the “point-free style” of programming more palatable. You don’t say |> fun a -> Foo (a) |> fun b -> Bar (b), you just say Foo |> Bar and that’s that. Admittedly, this occasionally leads to code that strikes me as somewhat cryptic: optionList |> List.collect Option.toList converts a list of Options into a list of the values of the Somes (i.e., flatMap id).


Another structural thing that slowed me down a bit is F#’s many kinds of types (I would say that F# has a plethora of kinds of types). I’m a believer in Functional in the Small, Object-Oriented in the Large, so I like to hang both data and responsibilities on a type. But with F#, I have to decide between classes (class), records (type), and discriminated unions (type |) (and 14 other kinds). The good news is that in my limited experience you can start with a record and then, if you need to refactor it into a class, it’s trivial (I may be insanely wrong about that, having only needed a class rather than a record once).

This proliferation of somewhat-overlapping concepts is about ensuring compatibility the Common Language Runtime and 95% of the time, it’s not something that you have to think about.


With my events in place and having decided on records, programming went very well. It’s trivial to use NUnit with F# and I quickly had 3 projects up and iterating: the model project, the CLI view & controller project, and my test suite.

I also used Xamarin Studio’s F# Interactive console regularly.
screenshot.

All of which was very pleasant, but I wonder if one downside of the “small functions doing one precise thing” of the functional approach is that it becomes easy to just keep composing function calls on the results of previous function calls rather than trying to create a consistent and sufficient data structure / object model. The drive towards refactoring a concise, task-driven API doesn’t seem as dominant since you’re simultaneously valuing the “easy to compose” tiny functions.

With small, easy-to-compose functions and a lot of flexibility about scoping you immediately start circling the issues of coupling and cohesion. General-purpose functions are, by definition, not very cohesive: they happen to be composed together to deliver value. Hmmm….


Even in a small program such as this, the lack of robust refactoring tools jumps out. When you’re learning a language, you just plough away at small programs, but as soon as you start writing even a few-module program, organizational and refactoring instantly becomes concerns.


Speaking of “small programs,” this program (which is focused, but not entirely trivial) is under 1KLoC including its test suite. I use craploads of higher-order functions, but with LINQ, I could structure a C# program very similarly. I also use pattern matching in several places and that would take more lines of C# code. I use the Option type, so that eliminates lines of C# dedicated to null-checking.

But in general I think I could (and would) write a very similarly-structured C# program to solve the problem. I would have written it faster, but not that much faster (maybe 10-15% faster). And the C# program would have, I think, about 20% or maybe even 33% more LOC; not that many more expressions but some more and then quite a few lines dedicated to closing parentheses and blocks. (Regarding my previous snarky comments about parentheses and indenting, I quote Walt Whitman:

Do I contradict myself? Very well, then I contradict myself, I am large, I contain multitudes.

)


One thing that became clear is that I haven’t come even close to mastering F#, despite having used it semi-regularly for a year. It’s learning curve is longer and higher than most languages. For instance, it now seems to me that I could have used a custom computation expression (dangerously close to the M-word) in a way that would have allowed me a lot of flexibility in evolving the app. Even more, I think that type providers might be an enormously important facility, but it’s an area where I haven’t even explored.

But as I said, I don’t think my productivity suffered all that much relative to C#, a language I’ve worked with since it’s very first beta. In other words, while the road to F# mastery is long, productivity comes much faster. I paid some penalty relative to C# on this project, I’ll pay less penalty on the next, less on the next after that… And I can see in a few smallish projects such as this, getting to the point where my productivity is in my standard range.

Scala was my day-to-day language for 2 years and I’d choose Scala over Java without hesitation (and no, Java 8 doesn’t change my mind). Mastering Scala involves understanding a very sophisticated and complex type system and there are certainly advantages to that, but (for me) the mental effort to know that type system has limited practical benefits relative to a less-sophisticated system. But I see in some of these F# facilities (such as type providers) the potential for techniques that are not just O(n) relative to my C# approaches. The F# learning curve is high, but I think that the long road to mastery might have more of a transformative change in my approach to programming.

Nonetheless, programming is programming and programming is hard. As soon as I thought I was ready to go, I discovered that some important data came in a variety of shapes. So I had to spend time discovering those patterns and working with them. That type of work is much easier in a language with a good set of higher-order list processing functions and built-in pattern matching. And, I think, the smaller functions characteristic of FP made it easier to isolate the change, but nothing defeats this essential characteristic of programming, which is that it’s far more about exceptions and business rules and capricious “that’s just the way it is” aspects than it is about mathematical elegance.


As for the application, in the first three days of this week, I averaged 5x my “doing it manually” productivity. So take that, Randall.

F# iOS Program: 39 lines of code

Xamarin loves F#!

fsharp_too

Of course you can use F# to program iOS and Android applications using Xamarin and Visual Studio!

namespace Simple

open System
open MonoTouch.UIKit
open MonoTouch.Foundation
open System.Drawing

type ContentView ( color : UIColor ) as self = 
    inherit UIView ()
    do 
        self.BackgroundColor < - color

type SimpleController ( ) =
    inherit UIViewController ()

    override this.ViewDidLoad () = 
        this.View <- new ContentView(UIColor.Blue)

[<Register ("AppDelegate")>]
type AppDelegate () =
    inherit UIApplicationDelegate ()

    let window = new UIWindow (UIScreen.MainScreen.Bounds)

    // This method is invoked when the application is ready to run.
    override this.FinishedLaunching (app, options) =
        let viewController = new SimpleController()
        viewController.Title <- "F# Rocks"

        let navController = new UINavigationController(viewController)
        window.RootViewController <- navController
        window.MakeKeyAndVisible ()
        true

module Main =
    [<EntryPoint>]
    let main args =
        UIApplication.Main (args, null, "AppDelegate")
        0

Screen Shot 2013-11-13 at 11.46.50 AM

Cheatsheet for iOS 7 Design Sizes

Helpful: http://ivomynttinen.com/blog/the-ios-7-design-cheat-sheet/

Natively Recognize Barcodes/QR Codes in iOS 7 with Xamarin.iOS

There have been great barcode-reading libraries available for Xamarin for some time, but iOS 7 has built-in barcode-recognition support.

There’s only one tricky bit: you have to tell the AVCaptureMetadataOutput what types of barcodes you’re interested in after you’ve added it to the AVCaptureSession. (I suppose what happens behind the scene is that the AVCaptureSession registers with the AVCaptureMetadataOutput the various types of barcodes it could recognize.)

UPDATE: This also works for realtime face detection! s/AVMetadataMachineReadableCodeObject/AVMetadataFaceObject/ and set AVMetadataObject.TypeFace!

Here’s a complete program in Xamarin.iOS that recognizes QR and standard Ean13 barcodes:

using System;
using System.Collections.Generic;
using System.Linq;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System.Drawing;
using MonoTouch.CoreGraphics;
using MonoTouch.AVFoundation;
using MonoTouch.CoreFoundation;

namespace SingleFileSolution
{
	public class ContentView : UIView
	{
		AVCaptureVideoPreviewLayer layer; 

		public ContentView(UIColor fillColor, AVCaptureVideoPreviewLayer layer, MyMetadataOutputDelegate metadataSource)
		{
			BackgroundColor = fillColor;


			this.layer = layer;
			layer.MasksToBounds = true;
			layer.VideoGravity = AVCaptureVideoPreviewLayer.GravityResizeAspectFill;

			Frame = UIScreen.MainScreen.Bounds;
			layer.Frame = Frame;
			Layer.AddSublayer(layer);

			var label = new UILabel(new RectangleF(40, 80, UIScreen.MainScreen.Bounds.Width - 80, 80));
			AddSubview(label);

			metadataSource.MetadataFound += (s, e) => label.Text = e.StringValue;

		}

		public override void LayoutSubviews()
		{
			base.LayoutSubviews();
			layer.Frame = Bounds;
		}
	}

	public class MyMetadataOutputDelegate : AVCaptureMetadataOutputObjectsDelegate
	{
		public override void DidOutputMetadataObjects(AVCaptureMetadataOutput captureOutput, AVMetadataObject[] metadataObjects, AVCaptureConnection connection)
		{
			foreach(var m in metadataObjects)
			{
				if(m is AVMetadataMachineReadableCodeObject)
				{
					MetadataFound(this, m as AVMetadataMachineReadableCodeObject);
				}
			}
		}

		public event EventHandler<AVMetadataMachineReadableCodeObject> MetadataFound = delegate {};
	}

	public class SimpleViewController : UIViewController
	{
		AVCaptureSession session;
		AVCaptureMetadataOutput metadataOutput;

		public SimpleViewController() : base()
		{
		}

		public override void DidReceiveMemoryWarning()
		{
			// Releases the view if it doesn't have a superview.
			base.DidReceiveMemoryWarning();
		}

		public override void ViewDidLoad()
		{
			base.ViewDidLoad();
			
			session = new AVCaptureSession();
			var camera = AVCaptureDevice.DefaultDeviceWithMediaType(AVMediaType.Video);
			var input = AVCaptureDeviceInput.FromDevice(camera);
			session.AddInput(input);

			//Add the metadata output channel
			metadataOutput = new AVCaptureMetadataOutput();
			var metadataDelegate = new MyMetadataOutputDelegate();
			metadataOutput.SetDelegate(metadataDelegate, DispatchQueue.MainQueue);
			session.AddOutput(metadataOutput);
			//Confusing! *After* adding to session, tell output what to recognize...
			foreach(var t in metadataOutput.AvailableMetadataObjectTypes)
			{
				Console.WriteLine(t);
			}
			metadataOutput.MetadataObjectTypes = new NSString[] {
				AVMetadataObject.TypeQRCode,
				AVMetadataObject.TypeEAN13Code
			};

			var previewLayer = new AVCaptureVideoPreviewLayer(session);
			var view = new ContentView(UIColor.Blue, previewLayer, metadataDelegate);

			session.StartRunning();
		
			this.View = view;
		}
	}

	[Register("AppDelegate")]
	public  class AppDelegate : UIApplicationDelegate
	{
		UIWindow window;
		SimpleViewController viewController;

		public override bool FinishedLaunching(UIApplication app, NSDictionary options)
		{
			window = new UIWindow(UIScreen.MainScreen.Bounds);

			viewController = new SimpleViewController();
			window.RootViewController = viewController;

			window.MakeKeyAndVisible();
			
			return true;
		}
	}

	public class Application
	{
		static void Main(string[] args)
		{
			UIApplication.Main(args, null, "AppDelegate");
		}
	}
}

Helpful list of Apple-supplied 3D buildings, turn-by-turn, etc.

My Favorite iOS 7 APIs Part 3 : CoreMotion (iPhone 5S only)

The new M7 coprocessor in the iPhone 5S makes pedometer apps trivial:

    if(CMStepCounter.IsStepCountingAvailable)
    {
        var counter = new CMStepCounter();
        //Last 8 hours
	counter.QueryStepCount(NSDate.FromTimeIntervalSinceNow(-8 * 60 * 60), NSDate.Now, NSOperationQueue.CurrentQueue, StepQueryHandler);
    }

    void StepQueryHandler(int nssteps, NSError error)
    {
        Console.WriteLine(nssteps);
    }

3D Buildings Not Showing in Your iOS App?

I totally forgot a frustrating detail about showing 3D buildings in iOS 7 : it doesn’t work in the simulator! You have to use a hardware device!

My Favorite iOS 7 APIs: Multipeer Connectivity

Multipeer Connectivity allows you to discover and share data with other iOS devices within Bluetooth radio range or on the same WiFi subnet. It is much easier to use than Bonjour.

I wrote a simple MPC chat program in Xamarin.iOS.

There’s necessarily a few hundred lines of code, but 90% of it is just the scaffolding necessary to support a four-view application. The actual discovery and communication is done with just a handful of code.

There are two phases for Multipeer Connectivity: Discovery and the Session phase. During the Discovery phase, one device acts as a coordinator or browser, and many devices advertise their interest in connecting. Devices advertise their interest in sharing a protocol defined by a string.

I created a base class DiscoveryViewController : UIViewController for both the advertising and browsing:

//Base class for browser and advertiser view controllers
public class DiscoveryViewController : UIViewController
{
	public MCPeerID PeerID { get; private set; }

	public MCSession Session { get; private set; }

	protected const string SERVICE_STRING = "xam-chat";

	public DiscoveryViewController(string peerID) : base()
	{
		PeerID = new MCPeerID(peerID);
	}

	public override void ViewDidLoad()
	{
		base.ViewDidLoad();

		Session = new MCSession(PeerID);
		Session.Delegate = new DiscoverySessionDelegate(this);
	}

	public void Status(string str)
	{
		StatusChanged(this, new TArgs<string>(str));
	}

	public event EventHandler<targs <string>> StatusChanged;
}

This base class holds a PeerID (essentially, the nickname for the device in the chat), an MCSession (the actual connection), and a SERVICE_STRING that specifies what type of MPC session I support (“xam-chat”). Additionally, it exposes an event StatusChanged (which is subscribed to by a UILabel in the DiscoveryView class (not shown, because it’s trivial).

Events relating to the MCSession are handled by ChatSessionDelegate, but those occur after discovery, so putting that aside for now, let’s look at how simple are the AdvertiserController and BrowserController subtypes of DiscoveryViewController:

public class AdvertiserController : DiscoveryViewController
{
	MCNearbyServiceAdvertiser advertiser;

	public AdvertiserController(string peerID) : base(peerID)
	{
	}

	public override void DidReceiveMemoryWarning()
	{
		// Releases the view if it doesn't have a superview.
		base.DidReceiveMemoryWarning();

		// Release any cached data, images, etc that aren't in use.
	}

	public override void ViewDidLoad()
	{
		base.ViewDidLoad();

		View = new DiscoveryView("Advertiser", this);
		var emptyDict = new NSDictionary();
		Status("Starting advertising...");

		advertiser = new MCNearbyServiceAdvertiser(PeerID, emptyDict, SERVICE_STRING);
		advertiser.Delegate = new MyNearbyAdvertiserDelegate(this);
		advertiser.StartAdvertisingPeer();
	}
}

class MyNearbyAdvertiserDelegate : MCNearbyServiceAdvertiserDelegate
{
	AdvertiserController parent;

	public MyNearbyAdvertiserDelegate(AdvertiserController parent)
	{
		this.parent = parent;
	}

	public override void DidReceiveInvitationFromPeer(MCNearbyServiceAdvertiser advertiser, MCPeerID peerID, NSData context, MCNearbyServiceAdvertiserInvitationHandler invitationHandler)
	{
		parent.Status("Received Invite");
		invitationHandler(true, parent.Session);
	}
}

public class BrowserController : DiscoveryViewController
{
	MCNearbyServiceBrowser browser;

	public BrowserController(string peerID) : base(peerID)
	{
	}

	public override void DidReceiveMemoryWarning()
	{
		// Releases the view if it doesn't have a superview.
		base.DidReceiveMemoryWarning();

		// Release any cached data, images, etc that aren't in use.
	}

	public override void ViewDidLoad()
	{
		base.ViewDidLoad();

		View = new DiscoveryView("Browser", this);

		browser = new MCNearbyServiceBrowser(PeerID, SERVICE_STRING);
		browser.Delegate = new MyBrowserDelegate(this);

		Status("Starting browsing...");
		browser.StartBrowsingForPeers();
	}

	class MyBrowserDelegate : MCNearbyServiceBrowserDelegate
	{
		BrowserController parent;
		NSData context;

		public MyBrowserDelegate(BrowserController parent)
		{
			this.parent = parent;
			context = new NSData();
		}

		public override void FoundPeer(MCNearbyServiceBrowser browser, MCPeerID peerID, NSDictionary info)
		{
			parent.Status("Found peer " + peerID.DisplayName);
			browser.InvitePeer(peerID, parent.Session, context, 60);
		}

		public override void LostPeer(MCNearbyServiceBrowser browser, MCPeerID peerID)
		{
			parent.Status("Lost peer " + peerID.DisplayName);
		}

		public override void DidNotStartBrowsingForPeers(MCNearbyServiceBrowser browser, NSError error)
		{
			parent.Status("DidNotStartBrowingForPeers " + error.Description);
		}
	}
}

Quite a few lines, but very straightforward: the advertiser uses the iOS class MCNearbyServiceAdvertiser and the browser uses the class MCNearbyServiceBrowser. The browser’s delegate responds to discovery by calling MCNearbyServiceBrowser.InvitePeer and the advertiser’s delegate responds to an invitation by passing true to the invitationHandler.

The Chat Session

When the invitation is accepted, it’s time for the ChatSessionDelegate to take over:

public class ChatSessionDelegate : MCSessionDelegate
{
	public DiscoveryViewController Parent{ get; protected set; }

	public ChatViewController ChatController
	{
		get; 
		set;
	}

	public ChatSessionDelegate(DiscoveryViewController parent)
	{
		Parent = parent;
	}

	public override void DidChangeState(MCSession session, MCPeerID peerID, MCSessionState state)
	{
		switch(state)
		{
		case MCSessionState.Connected:
			Console.WriteLine("Connected to " + peerID.DisplayName);
			InvokeOnMainThread(() => Parent.NavigationController.PushViewController(new ChatViewController(Parent.Session, Parent.PeerID, peerID, this), true));
			break;
		case MCSessionState.Connecting:
			Console.WriteLine("Connecting to " + peerID.DisplayName);
			break;
		case MCSessionState.NotConnected:
			Console.WriteLine("No longer connected to " + peerID.DisplayName);
			break;
		default:
			throw new ArgumentOutOfRangeException();
		}
	}

	public override void DidReceiveData(MCSession session, MonoTouch.Foundation.NSData data, MCPeerID peerID)
	{

		if(ChatController != null)
		{
			InvokeOnMainThread(() => ChatController.Message(String.Format("{0} : {1}", peerID.DisplayName, data.ToString())));
		}
	}

	public override void DidStartReceivingResource(MCSession session, string resourceName, MCPeerID fromPeer, MonoTouch.Foundation.NSProgress progress)
	{
		InvokeOnMainThread(() => new UIAlertView("Msg", "DidStartReceivingResource()", null, "OK", null).Show());

	}

	public override void DidFinishReceivingResource(MCSession session, string resourceName, MCPeerID formPeer, MonoTouch.Foundation.NSUrl localUrl, out MonoTouch.Foundation.NSError error)
	{
		InvokeOnMainThread(() => new UIAlertView("Msg", "DidFinishReceivingResource()", null, "OK", null).Show());
		error = null;

	}

	public override void DidReceiveStream(MCSession session, MonoTouch.Foundation.NSInputStream stream, string streamName, MCPeerID peerID)
	{
		InvokeOnMainThread(() => new UIAlertView("Msg", "DidReceiveStream()", null, "OK", null).Show());

	}
}

Again, this is mostly scaffolding, but be sure to note that it expects to be called on a background thread and uses InvokeOnMainThread to manipulate the UI. It also relies on the ChatViewController:

public class ChatViewController : UIViewController, IMessager
{
	protected MCSession Session { get; private set; }

	protected MCPeerID Me { get; private set; }

	protected MCPeerID Them { get; private set; }

	ChatView cv;

	public ChatViewController(MCSession session, MCPeerID me, MCPeerID them, ChatSessionDelegate delObj) : base()
	{
		this.Session = session;
		this.Me = me;
		this.Them = them;

		delObj.ChatController = this;
	}

	public override void DidReceiveMemoryWarning()
	{
		// Releases the view if it doesn't have a superview.
		base.DidReceiveMemoryWarning();

		// Release any cached data, images, etc that aren't in use.
	}

	public override void ViewDidLoad()
	{
		base.ViewDidLoad();

		cv = new ChatView(this);
		View = cv;

		cv.SendRequest += (s, e) => {
			var msg = e.Value;
			var peers = Session.ConnectedPeers;
			NSError error = null;
			Session.SendData(NSData.FromString(msg), peers, MCSessionSendDataMode.Reliable, out error);
			if(error != null)
			{
				new UIAlertView("Error", error.ToString(), null, "OK", null).Show();
			}
		};
	}

	public void Message(string str)
	{
		MessageReceived(this, new TArgs<string>(str));
	}

	public event EventHandler<targs <string>> MessageReceived = delegate {};
}

Again, it’s the simplicity that stands out: Session.SendData is used to transmit a string. The SendRequest event is wired to a UITextField and the MessageReceived event is wired to a UILabel:

public class ChatView : UIView
{
	readonly UITextField message;
	readonly UIButton sendButton;
	readonly UILabel incoming;

	public ChatView(IMessager msgr)
	{
		BackgroundColor = UIColor.White;

		message = new UITextField(new RectangleF(10, 54, 100, 44)) {
			Placeholder = "Message"
		};
		AddSubview(message);

		sendButton = new UIButton(UIButtonType.System) {
			Frame = new RectangleF(220, 54, 50, 44)
		};
		sendButton.SetTitle("Send", UIControlState.Normal);
		AddSubview(sendButton);

		incoming = new UILabel(new RectangleF(10, 114, 100, 44));
		AddSubview(incoming);

		sendButton.TouchUpInside += (sender, e) => SendRequest(this, new TArgs<string>(message.Text));
		msgr.MessageReceived += (s, e) => incoming.Text = e.Value;
	}

	public event EventHandler<targs <string>> SendRequest = delegate {};
}

The ChatViewController.Message method is called by the ChatSessionDelegate.DidReceiveData method.

And that’s really all there is to it.

Dynamic Type in iOS 7: Not Quite as “Dynamic” as You Might Think

One of the nice features in iOS 7 for old fogeys such as myself is that the user can use the general Settings to increase and decrease the fonts used in apps. This is called “Dynamic Type.” Judging by developer forums, I’m not the only one who thought that this was something that was built in to the various widgets. It’s not. To do this in your own app, you have to respond to the ContentSizeCategoryChanged notification and invalidate the layout in any widgets you want to have change size. In Xamarin.iOS, the code looks like this:

public class ContentView : UIView
{
    public ContentView()
    {
       var txt = new UITextView(UIScreen.MainScreen.Bounds);
       txt.Text = "Lorem ipsum dolor ...";
       ResetDynamicType();
       //Respond to notification of change
        UIApplication.Notifications.ObserveContentSizeCategoryChanged((s,e) => {
          ResetDynamicType();
        });
        AddSubview(txt);
    }
    public void ResetDynamicType()
    {
        txt.Font = UIFont.PreferredFontForTextStyle(UIFontTextStyle.Body);
    }
}

The crucial point being that you have a ResetDynamicType method (or whatever you want to call it) that you call both at initialization and then again every time you get notified of a request to change font size (if you want, you can read the new size from the e in the lambda). So “Dynamic Type” isn’t really anything special in terms of display: it’s still up to the application developer to have a function that’s called. What is dynamic is the value returned by UIFont.PreferredFontForTextStyle, which varies based on the user’s Settings.

div>