Ok, I think its possible I've misunderstood the correct way to implement an external screen on the iPad and it is causing me a lot of headaches.
Since this is a long post, what I'm trying to do is create and send a view to an external screen over VGA, and remove the screen once I'm done with it. I'm having retain count issues so can't get it to work.
I have a view controller that can be called up onto the iPad at any time. When this view loads (it is a remote, similar to Keynote presentation) I check for an external screen, then create a window and add a view to the extra monitor.
in my ipadViewController.h <-- the view that stays on the iPad
I have
#interface ipadViewController : UIViewController {
PresentationViewController *presentationView;
UIScreen *externalScreen;
UIWindow *externalWindow;
}
#property (nonatomic, retain) UIScreen *externalScreen;
#property (nonatomic, retain) UIWindow *externalWindow;
#property (nonatomic, retain) PresentationViewController *presentationView;
#end
(There is more, but that is the external screen stuff).
in ipadViewController.m:
#synthesize externalScreen;
#synthesize externalWindow;
#synthesize presentationView;
So I try to do a few things when the view loads:
Get the external screen (if possible)
Create apresentationViewController and add it to the extra screen
- (void)viewDidLoad {
[super viewDidLoad];
[self getExternalScreen];
[self createPresentationAndSendToWindow];
}
to get the screen I do the following getExternalScreen::
if ([[UIScreen screens] count] > 1)
{
for (UIScreen *currentScreen in [UIScreen screens])
{
if (currentScreen != [UIScreen mainScreen])
self.externalScreen = [currentScreen autorelease];
}
}
and to send the view to it createPresentationAndSendToWindow::
if (self.presentationPath == nil) return;
PresentationViewController *viewController = [[PresentationViewController alloc] initWithNibName:#"CanvasPresentation" bundle:nil];
self.presentationView = viewController;
[viewController release];
if (self.externalWindow == nil)
{
CGRect externalBounds = [self.externalScreen bounds];
self.externalWindow = [[[UIWindow alloc] initWithFrame:externalBounds] autorelease];
[self.externalWindow addSubview:self.presentationView.view];
self.externalWindow.screen = self.externalScreen;
[self.externalWindow makeKeyAndVisible];
}
in dealloc I try to cleanup with:
[presentationView release];
[externalScreen release];
//[externalWindow release]; <- that would crash
Problem I have is that when I dismiss the remoteViewController (it is modal), after releasing externalScreen has a retain count = 1 and externalWindow has retain count = 2.
The crash caused by externalWindow release disappears if I don't release presentationView (but then I'm leaking presentationView.
Your problem is here:
for (UIScreen *currentScreen in [UIScreen screens])
{
if (currentScreen != [UIScreen mainScreen])
self.externalScreen = [currentScreen autorelease];
}
Remove the autorelease. You shouldn't be releasing something you didn't create or retain.
you are autoreleasing externalView on
self.externalWindow = [[[UIWindow alloc] initWithFrame:externalBounds] autorelease];
and then you assign an autorelease view to it
self.externalScreen = [currentScreen autorelease];
you cannot release an autoreleased view, or it will crash.
Related
I have a major problem when trying to access a UIWebView that was created during ViewDidLoad, the UIWebView appears null
here is how i declare the property
#property (nonatomic, retain) UIWebView *detailsView;
the implementation
#implementation iPadMainViewController
#synthesize detailsView;
- (void)viewDidLoad
{
[super viewDidLoad];
detailsView = [[UIWebView alloc] initWithFrame:CGRectMake(500, 0, 512, 768)];
[self.view addSubView:detailsView];
}
When accessing from
- (void)loadDetailedContent:(NSString *)s
{
NSLog(#"%#", detailsView);
}
I get NULL, is it a normal behavior or am i doing something wrong?
here is the touchesBegan that is being called, from the views subclass that is being touched,
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
iPadMainViewController *mycontroller = [[iPadMainViewController alloc] init];
self.delegate = mycontroller;
[self.delegate loadDetailedContent:NewsId];
}
1st of all change you synthesize to
#synthesize detailsView = _detailsView
and allocate your uiwebvie
_detailsView = [[UIWebView alloc] initWithFrame:CGRectMake(500, 0, 512, 768)];
And try to push your ipadMainController in touchBegan to main screen and in vieDidLoad call loadDetailedContent
Are you sure that loadDetailedContent is not called before viewDidLoad? Set breakpoints in both methods and see which one gets hit first.
EDIT Since you updated the question with the code, it is easy to see why this problem happens. In touchesBegan, you instantiate the UIViewController and then call loadDetailedContent. This means that loadDetailedContent will be called before viewDidLoad.
viewDidLoad is called first when the view it controls has been created.
have been trying couple of hours now to make my iphone app universal. The mission was successful but have a strange problem. The navigation controller keeps pushing things without even pushing anything. The app doesn't crash but it gives me a message in the console
nested push animation can result in corrupted navigation bar
2012-02-06 10:52:07.701 ##$%^^$[54755:207] Finishing up a navigation transition in an unexpected state. Navigation Bar subview tree might get corrupted.
2012-02-06 10:52:07.704 !##$%^$%#[54755:207] Unbalanced calls to begin/end appearance transitions for <searchEditViewController: 0xc652150>.
and here is how i've set app the whole thing :
![navigation screen shot][1]
here is my code in the AppDelegate_iphone.h
#import <UIKit/UIKit.h>
#import "iPhoneView.h"
#import "AboutUsViewController.h"
#import "FavoritesViewController.h"
#class iPhoneView;
#interface AppDelegate_iPhone : NSObject <UIApplicationDelegate> {
UITabBarController *tabBarController;
UINavigationController *homeNavigationController;
UINavigationController *favouritesNavigationController;
AboutUsViewController *aboutUsViewController;
iPhoneView * search;
FavoritesViewController *favoritesViewController;
UIWindow *window;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet iPhoneView *search;
#property (nonatomic, retain) FavoritesViewController *favoritesViewController;
#end
and here is on my AppDelegate.m file
#import "AppDelegate_iPhone.h"
#import "iPhoneView.h"
#implementation AppDelegate_iPhone
#synthesize window,search,favoritesViewController;
#pragma mark -
#pragma mark Application lifecycle
- (void)applicationDidFinishLaunching:(UIApplication *)application
{ tabBarController = [[UITabBarController alloc] init];
homeNavigationController = [[UINavigationController alloc] init];
search = [[iPhoneView alloc] init];
[homeNavigationController pushViewController:search animated:NO];
favouritesNavigationController = [[UINavigationController alloc] init];
favoritesViewController = [[FavoritesViewController alloc]init];
[favouritesNavigationController pushViewController:favoritesViewController animated:NO];
aboutUsViewController =[[AboutUsViewController alloc] init];
UITabBarItem *item = [[UITabBarItem alloc] initWithTitle:#"επικοινωνία" image:[UIImage imageNamed:#"aboutus"] tag:0];
aboutUsViewController.tabBarItem = item;
[item release];
UITabBarItem *item2 = [[UITabBarItem alloc] initWithTitle:#"αγαπημένα" image:[UIImage imageNamed:#"favorites"] tag:0];
favouritesNavigationController.tabBarItem = item2;
[item2 release];
NSArray *tabBarControllerCollection = [NSArray arrayWithObjects:homeNavigationController,favouritesNavigationController,aboutUsViewController,nil];
[tabBarController setViewControllers:tabBarControllerCollection animated:NO];
[window addSubview:tabBarController.view];
[window makeKeyAndVisible];
}
- (void)applicationWillResignActive:(UIApplication *)application {
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application {
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application {
/*
Called as part of transition from the background to the inactive state: here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application {
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application {
/*
Called when the application is about to terminate.
See also applicationDidEnterBackground:.
*/
}
#pragma mark -
#pragma mark Memory management
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application {
/*
Free up as much memory as possible by purging cached data objects that can be recreated (or reloaded from disk) later.
*/
}
- (void)dealloc {
[tabBarController release];
[search release];
[favoritesViewController release];
[favouritesNavigationController release];
[aboutUsViewController release];
[window release];
[super dealloc];
}
#end
OK solved had connected the button 2 times with the same action in IB. Took me 48hours to figure it out!
I have been trying for days to get this code to work, but I have no idea what I am doing wrong. Everytime the app wakes up from sleep, or the user closes the app and opens it again (without closing the app from multitasking), I want a label value to change.
In my applicationDidBecomeActive, I am running a counter, which I want to display on whatever viewcontroller is open at that moment.
Code:
- (void)applicationDidBecomeActive:(UIApplication *)application {
counter = counter + 1;
W1G1 *view1 = [[[W1G1 alloc] initWithNibName:#"W1G1" bundle:nil] retain];
[view1 setlabel];
}
In my viewcontroller W1G1, I have the following code:
Code:
- (void) setlabel {
NSString *string = [NSString stringWithFormat:#"%d", counter];
vocabword.text = string;
}
I have imported W1G1 in my appdelegate, but the code does not run :( Please help!
Thanks
In the AppDelegate.m file, where you have
- (void)applicationDidBecomeActive:(UIApplication *)application {
counter = counter + 1;
W1G1 *view1 = [[[W1G1 alloc] initWithNibName:#"W1G1" bundle:nil] retain];
[view1 setlabel];
}
the variable counter being incremented is confined to the AppDelegate. In other words, your view controller doesn't know that it has been incremented.
I would suggest that you use NSUserDefaults to store the value of counter so that you can easily pass it between these view controllers. Either that, or you could allow for an input into the method setLabel, e.g.
- (void) setlabel:(int)counter {
NSString *string = [NSString stringWithFormat:#"%d", counter];
vocabword.text = string;
}
and then in the AppDelegate you'll want to do:
- (void)applicationDidBecomeActive:(UIApplication *)application {
counter = counter + 1;
W1G1 *view1 = [[[W1G1 alloc] initWithNibName:#"W1G1" bundle:nil] retain];
[view1 setlabel:counter]; // <-- now you're using counter
[self.window addSubview:view1];
}
1) When you say 'the code does not run' do you mean that? That is, if you put NSLogs in applicationDidBecomeActive: and in setLabel does it show the code is run?
2) I would suspect the code is running. But your code won't "show the counter on whatever view controller is open at that moment". Your code creates a new view (view1), but that view won't be displayed. It is not added as a subview to anything. Your code will also leak. You create a W1G1 object, but it is never released and you throw away any reference you have to it.
To achieve what you want, you could add a subview to the application's window. Depending how your app delegate is set up, something like the following should do the trick:
counter++;
W1G1 *viewController1 = [[W1G1 alloc] initWithNibName:#"W1G1" bundle:nil];
[viewController1 setlabel: counter];
[[self window] addSubview: [viewController1 view]]
// you'll want to save a reference to the viewController somehow so you can release it at a later date
Then in W1G1
- (void) setlabel: (int) counter;
{
NSString *string = [NSString stringWithFormat:#"%d", counter];
vocabword.text = string;
}
There are, of course, lots of other approaches you could take towards this problem. And you'll need some strategy for removing the W1G1 view that you are adding at some stage, otherwise you'll just get more and more views added.
Update: You ask (in comments) how to keep track of your viewController throughout lifetime of the app... One approach is to keep track of it in your appDelegate. In the header have something like:
#class W1G1;
#interface MyAppDelegate : : NSObject <UIApplicationDelegate>
{
// other decelerations
int counter;
W1G1 * _myW1G1
}
#property (nonatomic, retain) W1G1* theW1G1
In the .m file include
#synthesize theW1G1 = _myW1G1;
Probably in application:didFinishLaunchingWithOptions: create the viewController, set the property to refer to it, and add its view to the view hierarchy.
W1G1* theViewController = [[W1G! alloc] initWithNibName: #"W1G1" bundle: nil];
[[self window] addSubview: [theViewController view]];
[self setTheW1G1: theViewController];
[theViewController release];
Then when you want to access the viewController again from with the app delegate use [self theW1G1], e.g.
[[self W1G1] setlabel: counter];
I am new to iPhone programming and trying to grasp the concept of RootViewController.
Scenario:
I have 3 views
RootViewController - Parent View
SportsViewController - Sub View 1
CricketViewController - Sub View 2
Both the subview have to be in FullScreenMode, so tab-bar or navigation bar cannot be used.
At first, Sub View 1 is loaded which is having some content and a DONE button on it.
Once user press DONE button then Sub View 1 has to be unloaded and RootViewController should load the Sub View 2.
Query
I have successfully displayed SubView 1 and when user taps on DONE then I can unload it. But I did n't get how should I notify the RootViewController from Sub View 1 that Sub View 1 has unloaded and now it should load the Sub View 2?
Thanks in Advance
Paras Mendiratta
I think the easiest solution here is to use UINavigationController and just hide the navigation bar. You can use -setNavigationBarHidden:animated: to hide (or show) the nav bar.
one way is to implement a method like - (void)loadSecondView which does all u want to do when first view is unloaded. and then int doneButtonClicked-method u call this method like this: [super loadSecondView]; and also remove first view from superview.
I assume that the screen with the "Done" button is some kind of login screen. You actually do not need all the view controllers you have defined to do what you want.
Instead you could do like this:
At application launch set CricketViewController as the root view controller.
Immediately let CricketViewController present `SportsViewController" as a modal view controller, no animation.
As far as the user is concerned the sports view controller is the starting point.
Dismiss the modal view controller on the Done button tap, giving the user the illusion of going to the next view.
view1 = [[View1 alloc] initWithNibName:#"View1" bundle:nil]; //Create the first view
UINavigationController *navigationController1 = [[UINavigationController alloc] initWithRootViewController:view1];
navigationController1.navigationBar.tintColor =[UIColor blackColor];
view1 = navigationController1;
[window addSubview:view1.view];
[window makeKeyAndVisible];
This is general idea so please change according to your problem.
Here is my code where I tried to use delegate pattern.
The problem is the sub view 1 (videoPlayer) is not able to call the delegate methods. :(
ViewSwitcher.h - Root Controller
#class VideoPlayer; //Sub View 1
#class LandingPage; //Sub View 2
#protocol viewSwitcherDelegate
-(void)notifyViewSwitcher;
#end
#interface ViewSwitcher : UIViewController
{
id <viewSwitcherDelegate> delegate;
}
#property (nonatomic, retain) VideoPlayer *videoPlayer;
#property (nonatomic, retain) LandingPage *landingPage;
#property(assign) id <viewSwitcherDelegate> delegate;
-(void)loadSecondView;
-(void)delegateSetInSubView;
#end
ViewSwitcher.m - Implementation
#synthesize videoPlayer;
#synthesize landingPage;
//#synthesize delegate;
// 1.4 -> Declare the delegate constructor
- (id <viewSwitcherDelegate>)delegate
{
return delegate;
}
// 1.5 -> Declare the setDelegate method
- (void)setDelegate:(id <viewSwitcherDelegate>)v
{
delegate = v;
}
- (void)viewDidLoad
{
VideoPlayer *videoController = [[VideoPlayer alloc] initWithNibName:#"VideoPlayer" bundle:nil];
self.videoPlayer = videoController;
[self.view insertSubview:videoController.view atIndex:0];
[videoController release];
[super viewDidLoad];
}
-(void)loadSecondView
{
NSLog(#"Call for loading 2nd View");
}
VideoPlayer.h - SubView 1 (Movie Player)
#interface VideoPlayer : UIViewController <viewSwitcherDelegate>
{
ViewSwitcher *viewSwitcher;
MPMoviePlayerController *videoController;
}
#end
VideoPlayer.m - implementation
-(void)notifyViewSwitcher
{
NSLog(#"notifyViewSwitcher called.");
//Attempted to call the loadSecondView of ViewSwitcher
I tried calling delegate's method but in log nothing is printed.
[viewSwitcher loadSecondView];
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
// Setting the delegate
viewSwitcher.delegate = self;
return self;
}
- (void)viewDidLoad
{
NSString *urlStr = [[NSBundle mainBundle] pathForResource:#"bumper.mp4" ofType:nil];
NSURL *url = [NSURL fileURLWithPath:urlStr];
videoController = [[MPMoviePlayerController alloc] initWithContentURL:url];
videoController.controlStyle = MPMovieControlStyleNone;
[self.view addSubview:videoController.view];
videoController.view.frame = CGRectMake(0, 0, 480, 320);
videoController.fullscreen = YES;
// Remove the status bar from this view.
[[UIApplication sharedApplication] setStatusBarHidden:YES animated:UIStatusBarAnimationFade];
// TODO: This observer needs to be removed.
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(playbackStateChange:)
name:MPMoviePlayerPlaybackDidFinishNotification
object:videoController];
// Play the video.
[videoController play];
[super viewDidLoad];
}
// Receives notification once movie is finished.
-(void)playbackStateChange:(NSNotification*)notification
{
// TODO: Switch the view.
NSLog(#"Notification = %#", notification);
[self notifyViewSwitcher];
}
Here is the LOG:-
2011-08-03 02:44:47.333 My Video Player[24016:207] Notification = NSConcreteNotification 0x5768280 {name = MPMoviePlayerPlaybackDidFinishNotification; object = <MPMoviePlayerController: 0x5740940>; userInfo = {
MPMoviePlayerPlaybackDidFinishReasonUserInfoKey = 0;
}}
2011-08-03 02:44:47.337 My Video Player[24016:207] notifyViewSwitcher called.
I am having an issue with updating the contents of an "myInfoBox" object I created to be displayed while some background processes are done.
In the delegate method I am creating a new viewController:
-(void)loadMainView
{
myFirstViewController = [[MyFirstViewController alloc] initWithNibName:#"MyFirstView" bundle:nil];
navigationController = [[UINavigationController alloc] initWithRootViewController:myFirstViewController];
// myFirstViewController was retained again by the controller, release one
[myFirstViewController release];
navigationController.navigationBar.hidden = YES;
[window addSubview:navigationController.view];
[window makeKeyAndVisible];
// the next method is run after the "viewDidLoad" is finished loading
[myFirstViewController loadAlertViewForNewUser];
}
Following is my implementation of "myFirstViewController", it creates an instance of the "infoBox" class(I will show its code later):
- (void)viewDidLoad {
self.navigationController.navigationBar.frame = CGRectMake(0, 0, 0, 0);
self.navigationController.navigationBar.bounds = CGRectMake(0, 0, 0, 0);
self.myInfoBox = [[InfoBoxController alloc] initWithNibName:#"InfoBox" bundle:[NSBundle mainBundle]];
CGRect infoBoxFrame;
infoBoxFrame = CGRectMake(60, 120, 200, 200);
myInfoBox.view.frame = infoBoxFrame;
myInfoBox.i_statusLabel.text = #"Downloading Account Updates";
myInfoBox.i_titleLabel.text = #"Updating";
// disabled for testing
//myInfoBox.view.hidden = YES;
[self.view addSubview:myInfoBox.view];
[super viewDidLoad];
}
// this method is called after the view has been loaded by the delegate
- (void)loadAlertViewForNewUser
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Welcome!" message:#"Connect to download stuff from your account?"
delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:#"OK", nil];
alert.tag = 0;
[alert show];
}
// implementation of the alertview delegate
- (void)alertView:(UIAlertView *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (actionSheet.tag == 0)
{
if (buttonIndex == 0)
{ NSLog(#"button 0 was pressed"); }
if (buttonIndex == 1)
{
// this is the button that is pressed
[actionSheet removeFromSuperview];
[actionSheet release];
// tried using this also
//[self performSelectorOnMainThread:#selector(userInitialSetupMainThread) withObject:nil waitUntilDone:NO];
// do stuff and update the infobox about it
[self loadInfoBoxInitialUserSetup];
// tried using this as well
//[self performSelectorInBackground:#selector(loadInfoBoxInitialUserSetup) withObject:nil];
}
return;
}
}
- (void)loadInfoBoxInitialUserSetup
{
[self performSelectorOnMainThread:#selector(userInitialSetupMainThread) withObject:nil waitUntilDone:NO];
}
- (void)userInitialSetupMainThread
{
// fetch JSON data
NSDictionary *responseJSON = [NSDictionary dictionaryWithDictionary:[self getUserstuff]];
self.myInfoBox.i_statusLabel.text = #"Processing Recieved information";
// breakpoint - nothing changes in the view on the simulator
[myInfoBox.view setNeedsLayout];
// breakpoint - nothing changes in the view on the simulator
[myInfoBox.view setNeedsDisplay];
// breakpoint - nothing changes in the view on the simulator
[myInfoBox.parentViewController.view setNeedsLayout];
// breakpoint - nothing changes in the view on the simulator
[myInfoBox.parentViewController.view setNeedsDisplay];
// breakpoint - nothing changes in the view on the simulator
[myInfoBox performSelectorOnMainThread:#selector(updateValuesForTitle:) withObject:#"test" waitUntilDone:YES];
// breakpoint - nothing changes in the view on the simulator
[self.view setNeedsLayout];
// breakpoint - nothing changes in the view on the simulator
[self.view setNeedsDisplay];
// breakpoint - nothing changes in the view on the simulator
self.myInfoBox.i_statusLabel.text = #"Reloading...";
// breakpoint - nothing changes in the view on the simulator
[self readStuffFromDB];
sleep(2);
//disabled view removal for testing..
//[self.myInfoBox.view removeFromSuperview];
// breakpoint - nothing changes in the view on the simulator
}
What happens for me in the testing is that the myInfoBox object is created on screen when the -(void)loadMainView method is complete, then I can see on screen the "myInfoBox" in the background while the alertView in front (for testing...) at this point the screen is responsive and I can select the YES, once I select yes the delegate method is called.
As I commented in the source file, using breakpoints I am monitoring the simulator and following the code, never the less the changed label values are not reflected while I am still in the - (void)userInitialSetupMainThread method, but once it finishes the view updates with the latest set .text value!! grrr..
Also, the source for the myInfoBox class:
#interface InfoBoxController : UIViewController {
IBOutlet UILabel* i_titleLabel;
IBOutlet UILabel* i_statusLabel;
IBOutlet UIImageView* i_loadingImage;
IBOutlet UIImageView* i_background;
IBOutlet UIActivityIndicatorView* i_activityIndicator;
}
#property(nonatomic, retain) IBOutlet UILabel* i_titleLabel;
#property(nonatomic, retain) IBOutlet UILabel* i_statusLabel;
#property(nonatomic, retain) IBOutlet UIImageView* i_loadingImage;
#property(nonatomic, retain) IBOutlet UIImageView* i_background;
#property(nonatomic, retain) IBOutlet UIActivityIndicatorView* i_activityIndicator;
//- (void)updateValuesForTitle:(NSString *)title Label:(NSString *)label;
- (void)updateValuesForTitle:(NSString *)title;
#end
#implementation InfoBoxController
#synthesize i_titleLabel, i_statusLabel, i_loadingImage, i_background;
#synthesize i_activityIndicator;
//-(void)updateValuesForTitle:(NSString *)title Label:(NSString *)label
-(void)updateValuesForTitle:(NSString *)title
{
self.i_titleLabel.text = title;
self.i_statusLabel.text = title;
[self.i_titleLabel setNeedsDisplay];
[self.i_statusLabel setNeedsDisplay];
}
Sorry for the LOONG post :)
PLEASE ASSIST!
At the risk of sounding unhelpful, that's kind of just how it works. If you have long-running code in the main event loop (i.e., you don't explicitly create a thread or similar), the operating system won't be able to update the UI.
To update the UI while your code is running, you either need to run your complex operation in the back ground using thread, NSOperationQueue, etc, or just break it into smaller steps and return control to the main loop occasionally so that the UI can be updated.