iOS 8 Deprecated quite a few things- for instance if you did a map search using the Xamarin MapDemo, it uses a UISearchDisplayController but that’s now deprecated and you are meant to start using UISearchController instead.

Knowing which version of iOS your App is running on then becomes important. While I can use the older UISearchDisplayController on iOS 8, I can’t use the newer UISearchController on iOS 7.

Now I’ve been previously using this property to check if the OS is a certain version.

        public bool IsiOS8
        {
            get { return UIDevice.CurrentDevice.CheckSystemVersion(8, 0); }
        }

But I think it’s better to check if a version is >= 7 and for that purposes the MonoTouch.Foundation class provides NSProcessInfo() with it’s OperatingSystemVersion and Major and Minor properties. Note I’ve also changed IsiOS8 from a property to a function.

        public static bool IsiOS8()
{
return (new NSProcessInfo().OperatingSystemVersion.Major >= 8);
}

I’ve not mastered AutoLayout, but if you want to resize a label, there’s a few of things you need to do. The image below shows a slider used to control a font size.

 

Resizing a label with a slider

Here I’ve omitted the declarations but fontlabel is a UiLabel, Support.FontSize is a float, and fontSlider is a UISlider. This is the code.

            fontlabel = new UILabel()
            {
                Text = @"Font Size",
                Lines = 1,               
                TextColor = Support.uTextColor,
                BackgroundColor = Support.BackColor,
                LineBreakMode = UILineBreakMode.WordWrap,
                Frame = new RectangleF(10, 320, Frame.Width - 20, 30),
                Font = UIFont.FromName("Helvetica", Support.FontSize)
            };
            fontlabel.SizeToFit();
            AddSubview(fontlabel);
            fontslider = new UISlider(new RectangleF(5, 350, Frame.Width - 5, 30))
            {
                MinValue = 11f,
                MaxValue = 30f,
                Value = Support.FontSize
            };
            fontslider.ValueChanged += HandleFontSliderChanged;

        private void HandleFontSliderChanged(object sender, EventArgs e)
        {
            Support.FontSize = fontslider.Value;
            fontlabel.Font = UIFont.FromName("Helvetica", Support.FontSize);
            fontlabel.SizeToFit();
        }

Allow enough room for the label to fit at its largest size and having changed the font size in the Slider event, call SizeToFit() on the label. Otherwise you’ll find that the text is truncated when the label is made larger.

My App talks to a server over TCP/IP using a well defined packet protocol but I’d been experiencing difficulties of the “packets seem the wrong length” type. I got the server author to debug a conversation.

Now the server sends extra bytes in the middle of messages depending upon the server version of the Client App talking to it. I found this out early on. Anything under version 43 and it omitted two bytes in the middle of the packet.

My App was set to version 200. Androids start at 100, Windows Phone (the first App was created for it) start at 0. The version number is sent as a five char string with leading 0’s so my App sends 00200. It turned out that the part of the server that verified and classified messages only checked the last two digits. D’oh!

Hence my server seemed to be version 0. Until the bug is fixed, my App is now version 00260.

There are plenty of logging systems about for .NET. This site although it’s an advert for a .NET logging system has links and comparisons with many.  But sometimes all you need is a very simple logger, something as simple as appending a string to a text file. So here’s a 64 line logger that creates a dailyfile – for today it’s 20131004.log.

using System;
using System.IO;
using System.Threading.Tasks;

namespace TMRTaxi
{
    class Logger : IDisposable
    {
        public string FileName { get; set; }
        private StreamWriter sw;

        public Logger()
        {
            var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var cache = Path.Combine(documents, "..", "Library", "Caches");
            var logfile = Path.Combine(cache, @"log" + DateTime.Now.ToString("yyyymmdd") + ".log");
            FileName = logfile;
            var str = "Logging Startedn";

            sw = new StreamWriter(FileName, true);
            Log(str);

        }

        public void Pause()
        {
            if (sw != null)
            {
                sw.Flush();
                sw.Close();
                sw = null;
            }            
        }

        public void Log(string msg,string comment="")
        {
            if (sw == null)
                return;
            msg = DateTime.Now.ToString("T") + " : "+msg+(comment != ""?" ["+comment+"]":"");
            Task.Factory.StartNew(()=> sw.WriteLine(msg), TaskCreationOptions.LongRunning);           
        }

        public void Dispose(Boolean disposing)
        {
            if (sw != null)
            {
                sw.Close();
                sw = null;
            }    
        }

        public void Dispose()
        {
            Dispose(true); //i am calling you from Dispose, it's safe
            GC.SuppressFinalize(this); //Hey, GC: don't bother calling finalize later
        }

        ~Logger()
        {
            Dispose(false); //i am *not* calling you from Dispose, it's *not* safe
        }
    }
}

It could probably do with a bit of extra error checking. A try catch round the sw = new StreamWriter(FileName, true); line for instance.

These lines:

var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            var cache = Path.Combine(documents, "..", "Library", "Caches");
            var logfile = Path.Combine(cache, @"log" + DateTime.Now.ToString("yyyymmdd") + ".log");

create the log file in the caches folder.

This line Task.Factory.StartNew(()=> sw.WriteLine(msg), TaskCreationOptions.LongRunning); in Log() does a fire and forget. It runs it using the TPL (Task Parallel library). It seems to work fine.

Just creature a logger with

log = new Logger();
log.Log("App starting up");

Plus there’s an optional comment on the Log method.

Of course it would be nice if you can email the logs to yourself but programmatically that’s a no no. “Apfel verbietet es” as my German teacher might have said. (“Apple forbids it.”).

The workaround is to build a large text file from all the available log files (and remove them afterwards) then post it to a php script on a website and it emails it. I’ll post the C# code for that in a day or two.

Here’s proof- well it works in the simulator anyway!

ios-simulator