It’s kind of obvious in retrospect about enabling or disabling animation. It’s part of some code where I’ve added a UIImage onto a MkMapView (Apple’s iOS Controls for displaying a map), that centres the map on your current location when you click it. The button is a gun sight type icon and I’ve located in the bottom right edge of the map.

    private UIButton btnCurrentLoc; // defined at the class level

// in ViewDidLoad
    var ImageCurrentLoc = UIImage.FromBundle("images/currentloc.png");
    ImageCurrentLoc.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);

    btnCurrentLoc = new UIButton() { TintColor = UIColor.Black };
    btnCurrentLoc.SetImage(ImageCurrentLoc, UIControlState.Normal);
    btnCurrentLoc.Frame = new RectangleF(View.Frame.Width-50, View.Frame.Height - 100, ImageCurrentLoc.Size.Width, ImageCurrentLoc.Size.Height);

    btnCurrentLoc.TouchUpInside += (s, e) =>
                {
                    map.SetCenterCoordinate(map.UserLocation.Location.Coordinate,true);  // animated
                    //map.CenterCoordinate = map.UserLocation.Location.Coordinate;       // not animated, moves directly            
                }; 

  View.AddSubview(map);            // has to be this way round! map first then control
  View.AddSubview(btnCurrentLoc);

Note that you add the map first to the view then the button.

As it’s commented if you click the btnCurrentLoc button, it will animate the map so you can see it scroll to your location. If you comment out that line and uncomment the line below, when you click the button it will move there immediately.

iPhone MkMapView with home button

I wanted a RadioButton type of effect with three icons. Click one of the other three and it is set to blue and the other two are coloured red. It’s actually very easy once you know the trick. You have to tell iOS 8 that the each icon image is rendered AlwaysOriginal. UIImageRenderingMode is an enum with three values (AlwaysOriginal, AlwaysTemplate and Automatic).

To display the Icon in a colour, set the RenderingMode to AlwaysOriginal then create a UIButton from it and set the TintColor to whatever you want it to be. Image1 etc are declared at the class level as UIImage, btnOne etc is a UIButton and tbar is a UIToolbar.

  tbar = new UIToolbar(new RectangleF(0, 30, 320, 44)); // hard coded values for toolbar size/location
  View.AddSubview(tbar);

  var Image1 =UIImage.FromBundle("images/image1.png");
  Image1.ImageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal);
  btnOne = new UIBarButtonItem { Image = Image1, Title = "First Button", TintColor = UIColor.Blue };

// Repeat for button2, 3 etc
//  Add a click handler to each button
   btnOne.Clicked += (s, e) =>
            {
                ClearTints(); // three line method sets all buttons to red
                btnOne.TintColor = UIColor.Blue;
            };
tbar.SetItems(new []{btnOne,btnTwo,btnThree},false );

This shows three icons before and after the second one is selected.

Three icons before and after selection

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.

picture of emailed-log in gmailThis is a screenshot of a log viewed in Gmail.

This is a follow up to the post So I rolled my own logger. In that post I provided a simple logger class.

In this post I use http to send all the logs rolled up into one text file to a php script which emails the file to me. Remember, iOS does not allow you to send email programmatically.

        // helper function to retirn path
        public static string GetLocalFilesPath()
        {
            var documents = Environment.GetFolderPath(Environment.SpecialFolder.MyDocuments);
            return Path.Combine(documents, "..", "Library", "Caches");      
        }

    public static void EmailLogs()
    {            
        const string url = "http://example.com/email.php";
        var sb= new StringBuilder();
       
        try
        {
            Support.log.Pause();
            var dirInfo = new DirectoryInfo(Support.GetLocalFilesPath());
            var lstFiles = dirInfo.GetFiles("*.log");
            foreach (var info in lstFiles)
            {
                sb.AppendLine("-------------------------");
                var fInfo = info; // avoids closure bug
                sb.AppendLine(fInfo.Name);
                using (var sr = new StreamReader(fInfo.FullName))
                {
                    sb.Append(sr.ReadToEnd());
                }
            }
            var msg = WebUtility.UrlEncode(sb.ToString());
            var fullMsg = "z=xyz23&mid="+UNIT.MobileID+@"&alphasid="+UNIT.SystemID+@"&lui="+msg;
            Task.Factory.StartNew(() => HttpPost(url, fullMsg), TaskCreationOptions.LongRunning);
           
            foreach (var info in lstFiles)
            {
                info.Delete();
            }            
        }
        catch (Exception)
        {

        }
        finally
        {
            
        }            
        return; 
    }

Support is a class that includes a static instance of the logger class. This is a wrapper round a StreamWriter so the pause method closes the StreamWriter otherwise we’d be tring to read from a file that[‘s open in the StreamWriter. After the logs have been sent off the logger is restarted.

This rolls up all the logs it finds into one file using StringBuilder to append the file name and then each line in that log then url encodes it and calls the function httppost below which I found on Microsoft’s site

Note that for security I add in a few parameters. (MobileId and SystemID are static properties from another unit; I’ve changed that to UNIT as my unit name would be meaningless.) Once again I use fire and forget for calling httppost. Ie run it in another Task using the TPL. I’m deliberately not checking any error messages.

    public static string HttpPost(string url, string parameters)
    {
        try
        {
            //Create a WebRequest
            var req = (HttpWebRequest)WebRequest.Create(url);

            //Set the content type and method
            req.ContentType = "application/x-www-form-urlencoded";
            req.Method = "POST";

            //Get the total size of the post parameters and set the content length
            var bytes = System.Text.Encoding.UTF8.GetBytes(parameters);
            req.ContentLength = bytes.Length;

            //Write the data to the request stream
            Stream os = req.GetRequestStream();
            os.Write(bytes, 0, bytes.Length);
            os.Close();

            //Get the response
            WebResponse resp = req.GetResponse();
            if (resp == null) return null;

            //Get the response stream and read the response
            var sr = new StreamReader(resp.GetResponseStream());
            string result = sr.ReadToEnd().Trim();

            //Close the streams
            sr.Close();
            resp.Close();

            return result;
        }
        catch (Exception)
        {
            //Epic fail...
            return null;
        }
        finally
        {
            Support.log = new Logger();
        }
    }

Finally I have a small PHP script setup on a domain hosted on a shared server. Note the use of security parameters to stop spammers using this script to bombard you with spam. The parameters below should match the parameters in this line from above:

var fullMsg = "zvf=xyz23&mid="+UNIT.MobileID+@"&alphasid="+UNIT.SystemID+@"&lui="+msg;

This is the PHP script below, after validating that it’s a genuine request, it takes the three parameters, appends the log file to a local text file then emails it to the specified email address.

I have the error messages commented out as they’re only there for debugging purposes.