I have the following MonoTouch program:
using System.Drawing;
using MonoTouch.Foundation;
using MonoTouch.UIKit;
using System;
namespace Experiment
{
// This is just for the example, I use a singleton in my app to do this.
public class AppSettings
{
public static bool IsLoggedIn = false;
}
[Register ("AppDelegate")]
public class AppDelegate : UIApplicationDelegate
{
UIWindow window;
public override bool FinishedLaunching(UIApplication application, NSDictionary launchOptions)
{
UIViewController baseViewController = new RootViewController();
window = new UIWindow(UIScreen.MainScreen.Bounds);
window.AddSubview(baseViewController.View);
window.MakeKeyAndVisible();
return true;
}
static void Main(string[] args)
{
UIApplication.Main(args, null, "AppDelegate");
}
}
public class RootViewController : UITableViewController
{
public override void ViewDidAppear(bool animated)
{
base.ViewDidAppear(animated);
if (!AppSettings.IsLoggedIn) {
this.PresentViewController(new LoginPopupController(), false, () => {});
}
}
}
public class LoginPopupController : UIViewController
{
public override void LoadView()
{
View = new UIView(UIScreen.MainScreen.ApplicationFrame);
View.BackgroundColor = UIColor.White;
UIButton button = new UIButton();
button.SetTitle("press me", UIControlState.Normal);
button.Frame = new RectangleF(50, 50, 80, 80);
button.TouchUpInside += delegate {
LoginSucceeded();
};
button.BackgroundColor = UIColor.Purple;
View.AddSubview(button);
}
public void LoginSucceeded()
{
AppSettings.IsLoggedIn = true;
Console.WriteLine("This line causes multiple problems at random");
DismissViewController(true, () => {});
}
}
}
It has two controllers the RootViewController and the LoginPopupController. The FinishedLoading method adds the RootViewController to the window. The RootViewController in the ViewDidAppear method checks if the app is logged in. If not, it will present the LoginPopupController.
The LoginPopupController has a button, which when pressed will set IsLoggedIn to true, and dismiss itself.
Basically, I want a login window to appear if the user isn’t logged in, and then dismiss itself after it has entered login details into a singleton settings object.
However, the app is very unreliable at the moment. Pressing the “press me” button can cause the following to happen at random:
- Work as expected
- Freeze the app
- Crash the app
- Do nothing on first press, crash the app on the second press
The Console.WriteLine line has a big effect on this – if you remove it the code succeeds more often (but not always).
Can anyone figure out what is causing this problem? It seems like a race condition (as the results change between runs), however I can’t figure out what could be causing that.
I’m running the code on the simulator using iOS 5.1. I have MonoTouch version 5.2.10 installed with Mono 2.10.8.
I have done two changes in your code and it never crashed, at least for my number of tries.
First, move the
UIButtondeclaration to the class:Second, initialize the button with the
UIButton.FromType(UIButtonType)static method:The
UIButton()constructor had problems in previous versions of MonoTouch. In some versions it was not even available. I could not find anything specific for its current state, however creating buttons with the static method is the normal way to go, according to Apple docs.