Show activity indicator during application launch - objective-c

I am trying to add an activity indicator during startup. I did have a launch image, but I'd rather have just an indicator alone. I added the following to my app delegate, but the indicator doesn't appear.
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// *******Create activity indicator****
UIActivityIndicatorView *activity = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(225, 115, 30, 30)];
[activity setBackgroundColor:[UIColor clearColor]];
[activity setActivityIndicatorViewStyle: UIActivityIndicatorViewStyleGray];
[window addSubview: activity];
[activity release];
[activity startAnimating];
activity.hidden = FALSE;
// *******End activity indicator****
MainViewController *viewController = [[MainViewController alloc] initWithNibName:#"MainView" bundle:nil];
self.mainViewController = viewController;
[window addSubview:[mainViewController view]];
mainViewController.view.frame = CGRectMake(0, 20, 320, 411);
[window addSubview:[rootController view]];
[window makeKeyAndVisible];
#if !TARGET_IPHONE_SIMULATOR
[application registerForRemoteNotificationTypes:
UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound];
#endif
application.applicationIconBadgeNumber = 0;
// Hide indicator
[viewController release];
activity.hidden = TRUE;
[activity stopAnimating];
return YES;
}
I visited this question from back in 2009, but the solution didn't work for me.
iPhone-SDK:Activity Indicator during Startup?

For all those who needed this, and i know there were many...
(Made on Xcode version 4.2.1)
So...
In the AppDelegate.h add this:
#property (nonatomic, strong) UIImageView *splashView;
In the AppDelegate.m add this:
On the top of the page of cours #synthesize splashView;
And then:
- (void) splashFade
{
splashView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0, 320, 480)];
splashView.image = [UIImage imageNamed:#"Default.png"];
[_window addSubview:splashView];
[_window bringSubviewToFront:splashView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:2.0];
[UIView setAnimationDelay:2.5];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:_window cache:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(startupAnimationDone:finished:context:)];
splashView.alpha = 0.0;
[UIView commitAnimations];
//Create and add the Activity Indicator to splashView
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhite];
activityIndicator.alpha = 1.0;
activityIndicator.center = CGPointMake(160, 360);
activityIndicator.hidesWhenStopped = NO;
[splashView addSubview:activityIndicator];
[activityIndicator startAnimating];
}
- (void)startupAnimationDone:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context
{
[splashView removeFromSuperview];
}
The [UIView setAnimationDelay:2.5] is responsible for how long the splashView will be in front by the delay time you choose.
You can change the position of the indicator by changing the nubmers of x/y in:
activityIndicator.center = CGPointMake(160, 360);
At last, under the methode:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Just add this:
[self performSelector:#selector(splashFade) withObject:nil];
And there you go :)
Hope it helped.
Have a nice programming....

I don't think this is possible from looking at the docs for UIApplicationDelegate
The earliest your app is called is in
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
Which as the name suggests is when your app hasFinishedLaunching
The reason nothing happens when you show and hide the indicator is to do with threading. The user interface will only update at the end of your method where the net result of your changes will be that the indicator is hidden.

Another solution is to let the launchimage load and when your ViewController loads at the viewDidLoad, use overlay + indicator on top of your view with alpha below 1:
UIView *baseView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
[self.view addSubview:baseView];
[baseView setBackgroundColor:[UIColor blackColor]];
baseView.userInteractionEnabled = NO;
baseView.alpha = 0.4;
UIActivityIndicatorView *indicator = [[UIActivityIndicatorView alloc]initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
indicator.frame = CGRectMake(0.0, 0.0, 40.0, 40.0);
indicator.center = self.view.center;
[self.view addSubview:indicator];
[indicator bringSubviewToFront:self.view];
[indicator startAnimating];
Now comes the fun part, use delegate to remove the indicator + overlay when all your background threads finish to load up and simple call a method via your delegate:
- (void) onFinishLoading{
[indicator stopAnimating];
[baseView removeFromSuperview];
}
In order to stopAnimation and removeFromSuperView you might want to make baseView and indicator property + #synthesize

This isn't possible (as #Paul.S is saying). However, you can simulate this by adding a (static, so it's not animating) Default.png-splash-screen to your project.
In my opinion, though, you should rather invest in a better performance. For example: do you link your app with unused frameworks (eg. QuartzCore, MapKit) or something.
Starting an app should take 2 seconds max. At this time, you don't really need to show your user an activity-indicator. If it does take longer, you should take a look at what makes it so slow, rather than trying to hide it.

Related

Objective-C: Obscuring Data when in Background not working

I've been trying to obscure data when the application enters the background state by hiding it in the task switcher.
here is my AppDelegate.h file
#interface AppDelegate : UIResponder
<
UIApplicationDelegate,
MemberServicesManagerDelegate
>
{
UIWindow* window;
Reachability* reachbility;
}
#property(nonatomic, strong) UIViewController *mainViewController;
#end
This is my AppDelegate.m file
- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions
{ window = [[UIWindow alloc] initWithFrame:UIScreen.mainScreen.bounds];
window.rootViewController = StartupController.instance.startingViewController;
if(DEVICE == IPAD){
self.mainViewController = window.rootViewController.childViewControllers[0];
}
[window makeKeyAndVisible];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
//1
//self.window.hidden = YES;
//2
//UIViewController *image = [UIViewController new];
//image.view.backgroundColor = [UIColor blackColor];
//[window makeKeyAndVisible];
//[window.rootViewController presentViewController:image animated:NO completion:NULL];
//3
UIView *colourView = [[UIView alloc]initWithFrame:window.frame];
colourView.backgroundColor = [UIColor blackColor];
colourView.tag = 1234;
colourView.alpha = 0;
[window addSubview:colourView];
[window bringSubviewToFront:colourView];
[UIView animateWithDuration:0.5 animations:^{
colourView.alpha = 1;
}];
NSLog(#"BACK");
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
//1
//self.window.hidden = NO;
//2
//[window.rootViewController dismissViewControllerAnimated:NO completion:NO];
//3
UIView *colourView = [window viewWithTag:1234];
[UIView animateWithDuration:0.5 animations:^{
colourView.alpha = 0;
} completion:^(BOOL finished) {
[colourView removeFromSuperview];
}];
NSLog(#"ForeGround");
}
I tried these 3 implementations but It won't hide the view when I enter the multitask switcher.
I tried this with both simulator and real device but it still won't work. Can you help me with this?
Try doing it in applicationWillResignActive
applicationDidEnterBackground is apparently too late and the system has already made a screenshot for the task switcher.
More about application lifecycle

Opening new view on button click

I have a Navigation based Application named as diffView and in it I want to open new view on button click. For this a have created a view as file-new file-cocoa touch class-UIViewControllerSubclass named next1.
In diffViewAppDelegate.h I wrote as
IBOutlet UIButton *btn1;
#property (nonatomic,retain) UIButton *btn1;
-(IBAction)buttonPressed:(id)sender;
and in diffViewAppDelegate.m-
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
CGRect bounds=window.bounds;
UIView* view=[[UIView alloc]initWithFrame:bounds];
[view setBackgroundColor:[UIColor redColor]];
[window addSubview:view];
CGRect buttonFrame= CGRectMake(80, 240, 200, 30);
btn1=[[UIButton alloc] initWithFrame:buttonFrame];
[btn1 setTitle:#"space" forState:UIControlStateNormal];
[btn1.titleLabel setFont:[UIFont fontWithName:#"Verdana" size:20]];
[btn1 addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchDown];
[view addSubview:btn1];
[self.window makeKeyAndVisible];
return YES;
}
-(IBAction)buttonPressed:(id)sender
{
next1 * nxt=[[next1 alloc] initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:nxt animated:YES];
[nxt release];
}
I am not getting any error but when I click on the button nothing happens.
Please suggest me any solution.
Yes I have created the button in RootViewController but its not working.Even the button is not visible now. My code is like this-
CGRect buttonFrame= CGRectMake(80, 240, 200, 30);
btn1=[[UIButton alloc] initWithFrame:buttonFrame];
[btn1 setTitle:#"space" forState:UIControlStateNormal];
[btn1.titleLabel setFont:[UIFont fontWithName:#"Verdana" size:20]];
[btn1 addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchDown];
[self.view addSubview:btn1];
How i imagine it:
In your delegate you load - alloc/init the UINaviagationController and set its rootViewController property or just using initWithRootViewController: method when you init the NavigationController. Something like that.
viewController = [RootViewController alloc] init];
nvc = [[UINavigationController alloc] initWithRootViewController:viewController];
nvc.navigationBarHidden = YES;
[self.window setRootViewController:nvc];
[window makeKeyAndVisible];
In your RootViewController, from 'viewDidLoad:' method you create the button and add it to 'self.view' after that you implement the target selector and everything will be fine.
EDIT 1:
That is my application:didFinishLaunchingWithOptions: method in my AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch.
self.viewController = [[[ViewController alloc] init] autorelease];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:self.viewController];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
That is my RootViewController
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
CGRect buttonFrame= CGRectMake(80, 240, 200, 30);
UIButton *btn1=[[UIButton alloc] initWithFrame:buttonFrame];
btn1.backgroundColor = [UIColor greenColor];
[btn1 setTitle:#"space" forState:UIControlStateNormal];
[btn1.titleLabel setFont:[UIFont fontWithName:#"Verdana" size:20]];
[btn1 addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn1];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)buttonPressed:(id)sender
{
NSLog(#"sender: %#", sender);
}
#end

Multi view App Programatically

I want to know if it is possible to make multi view app without using the Interface Builder.
I know how to make it with just using Xcode and Storyboards, but I just want to be able make it programmatically.
For example : If I have a UIViewController A (default view) with a UIButton and than I have another UIViewController B with UIWebView so when I click on the UIButton of UIViewController A I want to be able to display the second View (Without IB).
How can I set the action to the UIButton to display my second View (Without Interface Builder) ?
You can add a target to your button:
[button addTarget:self action:#selector(buttonPressed:) forControlEvents:UIControlEventTouchUpInside];
Then in ControllerA, add this method:
-(void)buttonPressed:(id)sender
{
[self.superview addSubview:controllerB.view];
[self.view removeFromSuperview];
}
On ViewControllerA
- (void)viewDidLoad
{
UIButton *btn=[UIButton buttonWithType:UIButtonTypeRoundedRect];
[btn setFrame:CGRectMake(50.0f,200.0f,60.0f,30.0f)];
[btn setTitle:#"Next" forState:UIControlStateNormal];
[btn setTitleColor:[UIColor blackColor] forState:UIControlStateHighlighted];
[btn addTarget:self action:#selector(btnPressed:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
-(IBAction)btnPressed:(id)sender
{
NextViewController *nxt=[[NextViewController alloc]initWithNibName:nil bundle:nil];
[self.navigationController pushViewController:nxt animated:YES];
}
On viewControllerB
- (void)viewDidLoad
{
UIWebView *webView = [[UIWebView alloc] initWithFrame:CGRectMake(0,0, 320, 460)];
NSURL *targetURL = [NSURL URLWithString:#"http://developer.apple.com/iphone/library/documentation/UIKit/Reference/UIWebView_Class/UIWebView_Class.pdf"];
NSURLRequest *request = [NSURLRequest requestWithURL:targetURL];
[webView loadRequest:request];
[self.view addSubview:webView];
}
Make sure that in AppDelegate.h should be navigation controller like this
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[ViewController alloc] initWithNibName:#"ViewController" bundle:nil];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:self.self.viewController ];
self.window.rootViewController = navController;
[self.window makeKeyAndVisible];
return YES;
}

How to animate a UIImageview to display fullscreen by tapping on it?

I have an UIImageView in a UITableviewCell. When it is tapped, the UIImageView should animated to be displayed fullscreen. When the image is tapped when it is fullscreen it should shrink back to the original position.
How can this be achieved?
Add a gesture recognizer to the view controller.
Add the gesture Recognizer to your header file
#interface viewController : UIViewController <UIGestureRecognizerDelegate>{
UITapGestureRecognizer *tap;
BOOL isFullScreen;
CGRect prevFrame;
}
In your viewDidLoad add this:
isFullScreen = false;
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imgToFullScreen)];
tap.delegate = self;
Add the following delegatemethod:
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch;
{
BOOL shouldReceiveTouch = YES;
if (gestureRecognizer == tap) {
shouldReceiveTouch = (touch.view == yourImageView);
}
return shouldReceiveTouch;
}
Now you just need to implement your imgToFullScreen method.
Make sure you work with the isFullScreen Bool (fullscreen if it is false and back to old size if it's true)
The imgToFullScreen method depends on how you want to make the image become fullscreen.
One way would be:
(this is untested but should work)
-(void)imgToFullScreen{
if (!isFullScreen) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
//save previous frame
prevFrame = yourImageView.frame;
[yourImageView setFrame:[[UIScreen mainScreen] bounds]];
}completion:^(BOOL finished){
isFullScreen = true;
}];
return;
} else {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
[yourImageView setFrame:prevFrame];
}completion:^(BOOL finished){
isFullScreen = false;
}];
return;
}
}
The code from #AzzUrr1, small error corrections (brackets) and tapper implemented slightly different.
Worked for me. Now it would be great to have this implemented with a scrollView, that the user can zoom in/out if the picture is bigger.. Any suggestion?
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIGestureRecognizerDelegate>{
UITapGestureRecognizer *tap;
BOOL isFullScreen;
CGRect prevFrame;
}
#property (nonatomic, strong) UIImageView *imageView;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
isFullScreen = FALSE;
tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imgToFullScreen)];
tap.delegate = self;
self.view.backgroundColor = [UIColor purpleColor];
_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(10, 10, 300, 200)];
_imageView.contentMode = UIViewContentModeScaleAspectFill;
[_imageView setClipsToBounds:YES];
_imageView.userInteractionEnabled = YES;
_imageView.image = [UIImage imageNamed:#"Muppetshow-2.png"];
UITapGestureRecognizer *tapper = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(imgToFullScreen:)];
tapper.numberOfTapsRequired = 1;
[_imageView addGestureRecognizer:tapper];
[self.view addSubview:_imageView];
}
-(void)imgToFullScreen:(UITapGestureRecognizer*)sender {
if (!isFullScreen) {
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
//save previous frame
prevFrame = _imageView.frame;
[_imageView setFrame:[[UIScreen mainScreen] bounds]];
}completion:^(BOOL finished){
isFullScreen = TRUE;
}];
return;
}
else{
[UIView animateWithDuration:0.5 delay:0 options:0 animations:^{
[_imageView setFrame:prevFrame];
}completion:^(BOOL finished){
isFullScreen = FALSE;
}];
return;
}
}
I ended up using MHFacebookImageViewer. Integration is easy, no subclassing UIImageView, and it also has image zooming and flick dismiss.
Although it requires AFNetworking (for loading larger image from URL), you can comment out some code (about 10 lines) to remove this dependency. I can post my AFNetworking-free version if someone needs it. Let me know :)
One possible implementation would be to use a modal view controller with UIModalPresentationFullScreen presentation style.
Just finished a version in swift, just download and add into your project:
GSSimpleImageView.swift
And usage:
let imageView = GSSimpleImageView(frame: CGRectMake(20, 100, 200, 200))
imageView.image = UIImage(named: "test2.png")
self.view.addSubview(imageView)

Adding a TabBarController as the Subview of a View

I am loading a splash screen when my app starts. Then I want to load a TabBarController and it's ViewControllers. However, my TabBarController window does not scale to the screen size.
Probably 3/4 of the TabBar at the bottom is getting cut off and There is a slim aprox 20 pixel gap at the top of the screen below the status bar. How do I resize the TabBarController properly?
Here is the code in my SplashViewController loading the splash view, and the TabBarController:
-(void)loadView{
// Init the view
CGRect appFrame = [[UIScreen mainScreen] applicationFrame];
UIView *view = [[UIView alloc] initWithFrame:appFrame];
view.autoresizingMask = UIViewAutoresizingFlexibleHeight|UIViewAutoresizingFlexibleWidth;
self.view = view;
[view release];
splashImageView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"Splash.png"]];
splashImageView.frame = CGRectMake(0,0,320,458);
[self.view addSubview:splashImageView];
viewController = [[FlashCardViewController alloc] initWithNibName:#"FlashCardViewController" bundle:[NSBundle mainBundle]];
//viewController.view.bounds = [[UIScreen mainScreen]bounds];
viewController.title = #"Quiz";
viewController.tabBarItem.image = [UIImage imageNamed:#"puzzle.png"];
UIViewController *viewController2 = [[UIViewController alloc] initWithNibName:nil bundle:nil];
viewController2.title = #"Nada";
viewController2.tabBarItem.image = [UIImage imageNamed:#"magnifying-glass.png"];
//viewController.view.alpha = 0.0;
//[self.view addSubview:viewController.view];
tabBarController = [[UITabBarController alloc] init];
tabBarController.viewControllers = [NSArray arrayWithObjects:viewController, viewController2, nil];
[viewController2 release];
tabBarController.view.alpha = 0.0;
//tabBarController.tabBarItem.image = [UIImage imageNamed:#"State_California.png"];
//tabBarController.tabBarItem.title = #"State_California.png";
tabBarController.view.bounds = [[self view] bounds];
//tabBarController.view.frame = [[UIScreen mainScreen] applicationFrame];
[self.view addSubview:tabBarController.view];
timer = [NSTimer scheduledTimerWithTimeInterval:2.0 target:self selector:#selector(fadeScreen) userInfo:nil repeats:NO];
}
-(void) fadeScreen
{
[UIView beginAnimations:nil context:nil]; // begin animation block
[UIView setAnimationDuration:0.75]; // sets animation duration
[UIView setAnimationDelegate:self]; // sets the delegate for this block
[UIView setAnimationDidStopSelector:#selector(finishedFading)]; // Calls finishFading
self.view.alpha = 0.0; // // Fades the alpha to 0 over animation
[UIView commitAnimations]; // Commits this block, done
}
-(void) finishedFading
{
[UIView beginAnimations:nil context:nil]; // Begin animation block
[UIView setAnimationDuration:0.75]; // set duration
self.view.alpha = 1.0; // fades the view to 1.0 alpha over .75 seconds
//viewController.view.alpha = 1.0;
tabBarController.view.alpha = 1.0;
[UIView commitAnimations];
[splashImageView removeFromSuperview];
}
I've just completed pretty much the same and ran into the same problems but eventually I got it working.
Create a View Controller class in Xcode called Test1ViewController and add the following:
#interface Test1ViewController : UIViewController {
IBOutlet UITabBarController *tbc;
}
#property (nonatomic,retain) IBOutlet UITabBarController *tbc;
#end
Create a View XIB called Test1View
Add a TabBarViewController to the XIB
Set the File's Owner in the XIB to be the Test1ViewController.
Connect the tbc IBOutlet in the File's Owner to the Tab Bar Controller in the XIB.
Connect the view IBOutlet in the File's Owner to the View in the XIB.
In your SplashViewController.h add the property
Test1ViewController *tabBarViewController;
Synthesize the tabBarViewController in your SplashViewController.m.
Replace your TabBarController creation code in your loadView method in SplashViewController with the following:
tabBarViewController = [[Test1ViewController alloc] initWithNibName:
#"Test1View" bundle:[NSBundle mainBundle]];
tabBarViewController.view.alpha = 0.0;
[self.view addSubview:[tabBarViewController view]];
Here's the bit that was missing for me. In Test1ViewController.m, you need to add the following line to the viewDidLoad method:
self.view = tbc.view;
Finally, I also had to change the finishedFading method in SplashViewController.m to set the alpha to 1.0 on the tabBarViewController view.
-(void) finishedFading
{
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.75];
self.view.alpha = 1.0;
tabBarViewController.view.alpha = 1.0;
[UIView commitAnimations];
[splashImageView removeFromSuperview];
}
I hope this helps.
I finally found someting that works. Instead of:
tabBarController.view.frame = [[UIScreen mainScreen] applicationFrame];
or
tabBarController.view.bounds = [[self view] bounds];
Because I couldn't find and automatic or named settings for this size, I had to create my own rectangle that is the size of the screen minus the statusBar.
tabBarController.view.frame = CGRectMake(0,0,320,460);