Showing posts with label iOS. Show all posts
Showing posts with label iOS. Show all posts

Wednesday, October 21, 2015

HTTP Client PostAsync Fails in MonoTouch/iPhone

Problem:
Running tests on our cross platform solution and encountered an issue. 

I get an exception thrown on my call to postasjsonasync(). The exception says "A type load exception occured"

One step in our app sends an email out of the app using the HTTPClient libraries from MS.  This is known to cause issues.  I hit the boards stackoverflow, Xamarin, etc..  This is a fairly common problem.  The crazy thing is that we are using this call in our pcl. It works with no issues on Android and Windows Phone.  It is a problem on iOS.  It appears to be a mapping issue in the PCL.

Solution:
James Montemagno did come up with a solution. The issue with the error was assembly binding error.  The iOS version was binding to the native Windows System.Net.Http for .Net 4.5. 

We should be binding to the Xamarin version which is at

C:\Program Files(x86)\Reference Assemblies\Microsoft\Framework\Xamain.iOS\v1.0

Why?
"The reason for the redirect is that the Microsoft.Net.HttpClient packages contains the System.Net.HttpClient namespace but that already exists on iOS and Android (with slightly different features even). At runtime it will resolve to the wrong assembly and not use the (Xamarin-)native iOS one." (Thanks James!)


You can fix this problem by modifying the app.config in the Touch project.
 
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
        <dependentAssembly>
            <assemblyIdentity name="System.Net.Http" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
            <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="2.0.5.0" />
        </dependentAssembly>
    </assemblyBinding>



Source:
http://stackoverflow.com/questions/27521738/httpclient-failing
https://github.com/Krumelur/HttpClientTest/blob/master/HttpClientTest_iOS/app.config

Thursday, July 16, 2015

plugin not registered for type Cirrious.MvvmCross.Community.Plugins.Sqlite - Unified API

Problem:



I just successfully published the app to the iTunes store.  I had the application written and ready to publish when the wonderful Application Loader refused to load my app to the store!!  Why, because
it was not built to support the Unified API.  Easy fix just use the Xamarin upgrade to Unified Api and voila!  But Unified API is not compatible with MVVMCross SQLite Plugin (v 3.2.2)

Wait, not so fast.  I immediately had problems with the SQLite libraries for MVVMCross. 
This caused me about a week of pain working through all the interdepencies.  I was able to get the latest source code from https://github.com/MvvmCross/MvvmCross-SQLite/issues/39.  Then I built out the bits for support of my project.  I was able to compile and run the app.  It would crash each time I ran and attempted to load the screen which loaded  the sql lite plugin!!!

Error:
plugin not registered for type Cirrious.MvvmCross.Community.Plugins.Sqlite

I wracked my brain as to why the ui failed each time on the sqlite load.  I finally reread the api documentation on the MVVMCross wiki.  It finally hit me when I came across this added requirement for the iOS platform plugin. 



Solution:

You must include a second argument in the bootstrap action for the sqllite plugin.  The bootstrap needs the second argument in the interface constructor for iOS.  If you fail to include it then the path to the Touch plugin then the runtime will not load the plugin and will give you the error.

This is not a problem in Droid or Windows Phone builds.

 
using Cirrious.CrossCore.Plugins; 
using Cirrious.MvvmCross.Community.Plugins.Sqlite; 
using Cirrious.MvvmCross.Community.Plugins.Sqlite.Touch; 


public class SqlitePluginBootstrap 
: MvxLoaderPluginBootstrapAction<Plugins.Sqlite.PluginLoader, Plugins.Sqlite.Touch.Plugin> 
{ }




Source:
  1. https://github.com/MvvmCross/MvvmCross/wiki
  2.  https://github.com/MvvmCross/MvvmCross-SQLite/issues/39
  3. http://stackoverflow.com/questions/30648697/mvvmcross-community-plugin-for-sqlite-with-unified-api 
  4.  http://blog.alectucker.com/post/2015/01/19/sqlite-error-with-xamarinios-unified-api.aspx
  5.  https://bitbucket.org/twincoders/sqlite-net-extensions

ERROR: ERROR ITMS-90047: "Disallowed paths ( "iTunesMetadata.plist" ) found at: MyNewTool.app"

Solution:

For command line or IDE builds with XamarinVS
  1. Ensure "Project Properties -> iOS IPA Options -> Include Artwork in IPA" is not checked. (Or manually set the BuildIpa and IpaIncludeArtwork properties as mentioned above.)
    image
  2. Build the app.
  3. Submit the .ipa file using Application Loader.
or

<Target Name="_CompileITunesMetadata" DependsOnTargets="_DetectSdkLocations;_DetectAppManifest;_GenerateBundleName;_CompileAppManifest">
  <Message Text="Skipping CompileITunesMetadata task to prevent inclusion of iTunesMetadata.plist in the IPA" />
</Target>


Source:
  1. https://forums.xamarin.com/discussion/40388/disallowed-paths-itunesmetadata-plist-found-at-when-submitting-to-app-store/p1
  2. https://discussions.apple.com/thread/6997898?start=0&tstart=0
  3. https://bugzilla.xamarin.com/show_bug.cgi?id=29180#c0

Friday, June 12, 2015

IOS iPhone Simulator killing a running app

Problem:
Running my new app in the simulator and each time I start it up it defaults to the latest screen.
This is by design as it starts up where you  left off.  I need to give a demo and need to get it to start at their first screen.  How do I kill the session in memory?

Solution:
For iOS 7 & 8:
  • shift+command+H twice to simulate the double tap of home button
  • swipe your app's screenshot upward to close it
Source
http://stackoverflow.com/questions/18519799/ios-simulator-how-to-close-an-app

Monday, April 27, 2015

MVVMCross Extended Splash Screen Crossplatform (iOS/Android/WP)

Problem:
Trying to get the splash screen of the application to run longer then the default for each platform.  The typical answer I see posted on most sites is to use the default properties for each of the platform projects.  I wanted something I had more control of.  We are using the MVVMCross pattern for the application and so I wanted to put the solution into the PCL for use on all 3 platforms.  This solution creates a View with the splash screen image which can be extended via the timer function.  This allows us to display the image as long or short as we need it.


Solution:
I found several sites with tips and some hints from Stuart Lodge.  I managed to come up with a solution which builds on some code I found over at the Xamarin developer site.  The timer class should be placed in the PCL of your project.  It can then be referenced by your ModelView and this in turn binds to the View.

1.) Timer Class

using System;
using System.Collections.Generic;
using System.Diagnostics.Contracts;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace iReport.Core
{
 

    /// <summary>
    /// Missing from PCL, except if targeting .NET 4.5.1 + Win8.1 + WP8.1
    /// </summary>
    internal sealed class Timer : CancellationTokenSource
    {
        internal Timer(Action<object> callback, object state, int millisecondsDueTime, int millisecondsPeriod, bool waitForCallbackBeforeNextPeriod = false)
        {
            //Contract.Assert(period == -1, "This stub implementation only supports dueTime.");

            Task.Delay(millisecondsDueTime, Token).ContinueWith(async (t, s) =>
            {
                var tuple = (Tuple<Action<object>, object>)s;

                while (!IsCancellationRequested)
                {
                    if (waitForCallbackBeforeNextPeriod)
                        tuple.Item1(tuple.Item2);
                    else
                        Task.Run(() => tuple.Item1(tuple.Item2));

                    await Task.Delay(millisecondsPeriod, Token).ConfigureAwait(false);
                }

            }, Tuple.Create(callback, state), CancellationToken.None, TaskContinuationOptions.ExecuteSynchronously | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
                Cancel();

            base.Dispose(disposing);
        }
    }


}

2.)Model View

using Cirrious.MvvmCross.ViewModels;
using iReport.Core.Services.Collections;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;


namespace iReport.Core.ViewModels
{
    public class TimerViewModel : MvxViewModel
    {
        private DateTime? _whenToFinish;
        private Timer _timer;
        public TimerViewModel()
        {
                    _timer = new Timer(OnTick, null, 1000, 1000);
                    _whenToFinish = DateTime.UtcNow.AddSeconds(3);
        }

        #region Timer Test
            private void OnTick(object state)
            {
                if (!_whenToFinish.HasValue)
                    return;

                if (DateTime.UtcNow >= _whenToFinish.Value)
                {
                    base.ShowViewModel<MainViewModel>();

                    _whenToFinish = null;
                }
            }

        
        
        #endregion

    }
}


3.)View


using Cirrious.MvvmCross.Binding.BindingContext;
using Cirrious.MvvmCross.Touch.Views;
using Cirrious.MvvmCross.ViewModels;
using iReport.Core.ViewModels;
using iReport.Touch.Controls;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System;
using System.Collections.Generic;
using System.Drawing;
using System.Text;

namespace iReport.Touch.Views
{

    [Register("TimerView")]
    public class TimerView : MvxViewController
    {
        private BindableProgress _bindableProgress;


        public override void ViewDidLoad()
        {

            View = new UIView() { BackgroundColor = UIColor.Gray };

            base.ViewDidLoad();

            this.NavigationController.ToolbarHidden = true;
            this.NavigationController.NavigationBarHidden = true;

            UIImage splashscreen = MaxResizeImage(UIImage.FromFile("Default.png", UIScreen.MainScreen.Bounds.Width,UiScreen.MainScreen.Bounds.Height);

             UIImageView splashView = new UIImageView(splashscreen);
             Add(splashView);

            var set = this.CreateBindingSet<TimerView, Core.ViewModels.TimerViewModel>();
           

          
            set.Apply();

        }
    }
 // resize the image to be contained within a maximum width and height, keeping aspect ratio
public UIImage MaxResizeImage(UIImage sourceImage, float maxWidth, float maxHeight)
{
    var sourceSize = sourceImage.Size;
    var maxResizeFactor = Math.Max(maxWidth / sourceSize.Width, maxHeight / sourceSize.Height);
    if (maxResizeFactor > 1) return sourceImage;
    var width = maxResizeFactor * sourceSize.Width;
    var height = maxResizeFactor * sourceSize.Height;
    UIGraphics.BeginImageContext(new SizeF(width, height));
    sourceImage.Draw(new RectangleF(0, 0, width, height));
    var resultImage = UIGraphics.GetImageFromCurrentImageContext();
    UIGraphics.EndImageContext();
    return resultImage;
}



}

Source:

  1. http://stackoverflow.com/questions/5429746/how-to-get-width-and-height-of-iphone-ipad-using-monotouch
  2. http://forums.xamarin.com/discussion/4170/resize-images-and-save-thumbnails
  3. http://forums.xamarin.com/discussion/27327/ios-background-image-scale
  4. http://stackoverflow.com/questions/20447787/system-threading-timer-issue-only-timer-in-mvvmcross
  5. http://stackoverflow.com/questions/15961664/viewmodel-lifecycle-when-does-it-get-disposed
  6. https://code.msdn.microsoft.com/windowsapps/Splash-screen-sample-89c1dc78
 

Tuesday, April 21, 2015

Navigation Bar customization iOS (NavigationItem.SetRightBarButtonItems)

Working an issue on a project.  We needed to modify the navigation bar in iOS.
I was not sure how to do this but turns out we can use the NavigationItem class in the MonoTouch library. 

var btnEmail = new UIBarButtonItem(UIImage.FromFile("image/mail.png"),UIBarButtonItemStyle.Plain, (s,e) => {});
NavigationItem.SetRightBarButtonItems(new UIBarButtonItem[] { btnEmail}, true);


Source:
  1. http://forums.xamarin.com/discussion/16413/navigation-uibarbuttonitem-creation

Friday, March 13, 2015

MVVMCross iOS: How to trigger RowSelected Table View?

I was struggling with how to raise an MVVM event on a click within a tableview.
Fortunately, Stuart Lodge has come through with a great demo of how this all works.
His N+17 video about 47 minutes in gives the details for iOS.  He also has a demo
in his MVVM samples library.  I lifted the pertinent code out of the repo.  The key is to bind
your MVVM command to the SelectionChangeCommand which is a property of the TableView
row item.

Sample:

ModelView:

new Cirrious.MvvmCross.ViewModels.MvxCommand<DilbertItem>((dilbertItem) =>
{   
// note that we can only pass an id here - do *not* serialiase the whole dilbertItem ShowViewModel<DilbertDetailViewModel>(new { id = dilbertItem.Id });
});


View:

// binding
set.Bind(source) .For(s => s.SelectionChangedCommand) .To(s => s.ShowDetailCommand);



Source:
N=17 https://www.youtube.com/watch?v=h0Eww89c9DM&feature=youtu.be&t=47m30s

http://stackoverflow.com/questions/17712589/mvvmcross-ios-how-to-trigger-rowselected-on-a-custom-tableviewsource-using-crea

Wednesday, February 4, 2015

iOS UISegmentedControl custom binding in MVVMCross

Working on a UI screen for an MVVM view using the UISegmented Control.  My view needed to handle the SelectedSegment event which is not part of the MVVMCross libraries.  The good news is that MVVMCross Framework is extensible.  Stuart Lodge did 2 of his N+1 series on this particular subject.  There was some confusion on my part about how exactly to do this until I hit on this stackoverflow post.  The author provided the target binding for the Segmented control with enough hints to get me to the working solution.

Solution:
Create the file MvxUISegmentedControlSelectedSegmentTargetBinding.cs and place it in the Touch project:

1.)MvxUISegmentedControlSelectedSegmentTargetBinding .cs

public class MvxUISegmentedControlSelectedSegmentTargetBinding : MvxPropertyInfoTargetBinding<UISegmentedControl>
{
    public MvxUISegmentedControlSelectedSegmentTargetBinding(object target, PropertyInfo targetPropertyInfo)
        : base(target, targetPropertyInfo)
    {
        this.View.ValueChanged += HandleValueChanged;
    }

    private void HandleValueChanged(object sender, System.EventArgs e)
    {
        var view = this.View;
        if (view == null)
        {
            return;
        }
        FireValueChanged(view.SelectedSegment);
    }

    public override MvxBindingMode DefaultMode
    {
        get { return MvxBindingMode.TwoWay; }
    }

    protected override void Dispose(bool isDisposing)
    {
        base.Dispose(isDisposing);
        if (isDisposing)
        {
            var view = this.View;
            if (view != null)
            {
                view.ValueChanged -= HandleValueChanged;
            }
        }
    }
}

2.)Touch project Setup.cs file needs to register the target factories

protected override void FillTargetFactories(IMvxTargetBindingFactoryRegistry registry)
{
        registry.RegisterPropertyInfoBindingFactory(typeof(MvxUISegmentedControlSelectedSegmentTargetBinding), typeof(UISegmentedControl), "SelectedSegment");
}
The key here is that the 3rd argument must be match the SelectedSegment property in the UISegmentedControl.

3.)Core project ViewModel needs to include an integer property to bind against the SelectedSegment property. 

ViewModel

private int _selectedSegment

public int SelectedSegment
{
get {return _selectedSegment;}
set
{
   _selectedSegment = value;
   RaisePropertyChanged(); => SelectedSegment;
}


4.)  Touch project View needs to bind the SelectedSegment in the ViewModel to the SelectedSegment in the Mvx control

View Model

public override void ViewDidLoad()
{
....
var segmentControl = new UISegmentedControl();
....
var set = this.CreateBindingSet<View,ViewModel>();

set.Bind(segmentControl).For(sm=>sm.SelectedSegment).To(vm=>vm.SelectedSegment);
...


Source:

1.)mvvmcross-and-uibutton-selected-uisegmentedcontrol-bindings-ios
2.)Stuart Lodge's github repo
3.)MVVMCross N+1 N28 (Custom Binding)
4.)MVVMCross N+1 N19 (Custom Control)
5.)

Wednesday, October 15, 2014

MVVMcross mvxException failed to construct and initialize viewmodel check MvxTrace fo more information

Problem:

We are trying to construct the iOS layer to our MVVMcross project.  We have built the core for the initial ViewModel and wanted to add the iPhone layer.  The project when in just fine and the Mac Host even compiled everything. 

Once I ran the solution, I get this runtime error in the iPhone Simulator.

Solution:

Lots of great information about possible solutions at stackoverflow.  However, my problem was the SQLite plugin.  I neglected to add the plugin to my iPhone Layer and once I added it the app runs fine.


Source:
http://stackoverflow.com/questions/18940820/how-do-you-initialize-themvvmcross-sqlite-plugin

Friday, September 26, 2014

Xamarin Error 429 - clocks not synced

I am building out a disconnected network for our VS/Xamarin iOS build environment. 

Problem:
I have successfully paired the Mac and Windows boxes on our local network.  I noted that there is a discrepancy in the clocks between the two machines.  How to fix this problem.

Solution:
Make your Mac the time server

  1. Unload the current npd daemon.
    • sudo launchctl unload /System/Library/LaunchDaemons/org.ntp.ntpd.plist 
  2. Edit the ntp-restrict.conf
    • /etc/ntp-restrict.conf
    • Remove the “noquery” from the 1st two restrict lines:
  3. Now load the npd file again
    • sudo launchctl load /System/Library/LaunchDaemons/org.ntp.ntpd.plist
  4. Test npd to ensure it is running
    • sudo ntpdate -u localhost
On your Windows PC
  1. Open Date and Time Dialog
  2. Select the Internet time tab
  3. Change Settings
  4. Select Synchronize with and Internet time server.
  5. Place the IP Address of the Mac you are using as the time server (192.168.0.100) in the Server block
  6. Update Now
  7. OK
Now
  1. Open up command window as admin
  2. type in command: w32tm /config /manualpeerlist:192.168.0.100 /syncfromflags:MANUAL
 Now the windows box will sync its time with the Mac box and should not have the 429 errors any longer.


Source
http://macmule.com/2013/12/15/how-to-use-osx-server-as-a-time-server/

The remote server returned an error: 429 (Xamarin Visual Studio iOS error 429)

Problem:
VS not working (The remote server returned an error: 429)

Solution:
My clocks were off by one hour inspite of showing the same time.  The windows box had an incorrect setting for the timezone UTC+1.  It had been manually advanced by one hour.  This meant that the times between the Windows box running VS and the Mac Host had a difference of 1 hour.
Anything over 3 minutes will throw an error in the compiler.






http://forums.xamarin.com/discussion/17062/vs-not-working-the-remote-server-returned-an-error-429

Tuesday, September 23, 2014

Installing Xamarin.iOS on Windows

Xamarin site has great how to guides for installing their product for use with Visual Studio.
We are writing our first iPhone app using C#, Xamarin and Mvvmcross.




How to install:

http://developer.xamarin.com/guides/ios/getting_started/installation/windows/#Connecting_to_the_Mac_Build_Host