FullScreen Loading View didn't work - objective-c

I have been working on a fullscreen loading view for my apps, but it can't block any user interaction. The way I implement it is like this:
Create a singleton object - LoadingView
Call [LoadingView show] - add the loading view to [[[UIApplication sharedApplication] delegate] window]
So I want to ask :
Is my concept wrong?
Are there any method calls that can disable all user interaction to my apps?
Is there another better way to do this? (I prefer knowing about the principle inside than just using others' libraries)
Thanks

I use such way to block user interaction:
create UIView with window frame
set view's user interaction enabled to true
(optional) add UIActivityIndicator to view
add view to window subviews
when I need to show it I set hidden to NO and use bringSubviewToFront function to show loading view
when I don't need it I set hidden to YES and use sendSubviewToBack
id application = [[UIApplication sharedApplication] delegate];
UIView *loadingView = [[UIView alloc] initWithFrame:[[application window] frame]];
loadingView.userInteractionEnabled = YES;
loadingView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
[[application window] addSubview:loadingView];

Are you wanting to create a splash screen when the application starts? If so, all you need to do is add an image file called Default.png and/or Default#2x.png (for retina displays) to your project. This image will work as a splash screen for when the app launches.
You can also control the splash screen info.plist file.
Read more about the iOS launch screen here.

Related

Add subview to active viewController from AppDelegate

I'm creating a application with an sqlite database. I update the database with information retrieved from a web service. I call the web service from AppDelegate like this:
-(void)applicationDidBecomeActive:(UIApplication *)application{
// get new information from web service
// update sqlite database
}
The web service can take quite a long time so I want to add a UIActivityIndicatorView to whatever viewController that is active. And of course, remove it when then update is done.
Ideas?
- (void)applicationDidBecomeActive:(UIApplication *)application
{
testView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 420, 480)];
testView.backgroundColor = [UIColor redColor];
[self.window.rootViewController.view addSubview:testView];
}
Then whenever you are done do:
[testView removeFromSuperview];
In each of your view controllers (or common super class view controller) listen for UIApplicationDidBecomeActiveNotification notification which is being sent when application becomes active.
This way you can have custom logic for each view controller without coupling app delegate to other parts of your code by using lots of ifs (if you need to distinguish which view controller is active one).
Because your view hierarchy can take any form, tracking the currently visible view controller is something you will have to do yourself. The exception: if everything in your app happens within a UINavigationController, you can always get the current view controller with this.
[navigationController topViewController];
If all you need to do is present an overlay, however, you can just add that view to the root view controller's view; all child view controllers are just presented as subviews anyway.
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
[self.window.rootViewController.view addSubview:activityIndicator];
[activityIndicator startAnimating];
Manually throwing views into the mix like this is not very elegant, though. I would consider posting notifications when various network events occur, and letting each view controller update itself appropriately.

Overriding NSWindowController

Got a small question, i'm busy creating an OSX application. In my first view (appdelegate) i got a login screen, but after the users logged in i want (flip the logincontroller (main.xib) to remove the login screen and open a new NSWindowcontroller.
What is the best way to do that? I tried;
Second = [[SecondController alloc] initWithWindowNibName:#"SecondController"];
[[Second window] makeFirstResponder:nil];
But now the second controller appears but the first controller stays. In iOS development i'm doing (want the same thing but than for OSX)
CategoriesViewController *tableController = [CategoriesViewController alloc];
tableController.managedObjectContext = [self managedObjectContext];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:tableController];
Carmin is correct but you could do
[Yourwindow close:nil];
Each window controller controls one window. You have two window controllers. You have two windows. iOS only displays one window at a time where OSX displays multiple windows at a time. You need to NSWindow-close the login window to make it disappear. You may also desire to release the login window if the NSWindow-releasedWhenClosed property is not set.

Trying to dismiss subview and UIView

I'm still very new to iOS developing. In fact, if there is a super noob, I would be one :p. Currently I am working on creating an IBAction button that accesses a subview. I have 2 ViewControllers, AddClientVC and NewClientVC, both with .nib files. So basically, inside my AddClientVC I implement an IBAction button with the following code:
- (IBAction)buttonPressed:(id)sender
{
UIView *transparentBG = [[UIView alloc] initWithFrame:CGRectMake(-5, -5, 1500, 2500)];
transparentBG.backgroundColor = [UIColor blackColor];
transparentBG.opaque = NO;
transparentBG.alpha = 0.5;
[self.view addSubview:transparentBG];
transparentBG.center = transparentBG.center;
vc = [[NewClientVC alloc] initWithNibName:#"NewClientVC" bundle:nil];
[self.view addSubview:vc.view];
vc.view.center = self.view.center;
}
As you can see I implemented a UIView as a transparent background. Basically AddClientVC --> Transparent Background --> NewClientVC. Now I have created another IBAction button but this time inside NewClientVC as a function to dismiss the accessed subview which looks like this:
- (IBAction)saveDismiss:(id)sender
{
[self.view removeFromSuperview];
}
The problem I'm having right now is when I click the saveDismiss button it only removes the subview that I called previously on AddClientVC but it didn't remove the transparent background I have created as a UIView. So the problem is how do I implement an action which simultaneously removes my subview and the UIView transparent background I created.
I need all the help I can get :)
I'm not too sure I fully understand what you want to happen, but maybe you could try something like this?
- (IBAction)saveDismiss:(id)sender
{
[vc removeFromSuperView];
[self.view removeFromSuperview];
}
I recommend not to manage your screens by adding subviews manually but instead use
- (void)presentModalViewController: (UIViewController *)modalViewController
animated: (BOOL)animated
method on your root viewController.
Or better instantiate a UINavigationController and use push and pop methods to drill down/up your views.
See apple reference here
Do not worry about code execution speed and stay confident in apple's SDK. UIKit is optimized for best user experience. Trying to boost your code by doing inappropriate SDK use is, in my opinion, a risky strategy. ;) – Vincent Zgueb
Sorry Vincent but I don't agree with you. I reached here because I want to implement an gesture that adds a sub-view for my view, which will be the navigation of my app.
[self.view addSubview:ctrl.view];
is faster presenting the view than
[self.navigationController presentModalViewController:ctrl animated:NO]
and by the way, the solution to the topic in my case was:
[self.view sendSubviewToBack:ctrl.view];

Xcode Adding Subview on entire screen above everything

I want to use addSubview method to add new view on my screen. However, new view must also include navigation bar etc. which means it should include entire screen. What should i do?
Whenever i try to addSubview it always shows new view under navigation bar.
I don't want to use pushViewController or presentModelViewController because new added view will be low opacity and i can see background but i do not want to interact with background objects like bar buttons table etc.
Sorry for english, i hope, i clearly told what problem is.
Just set the frame property of the view you add before, and set it with screen bounds.
[myView setFrame:[[UIScreen mainScreen] bounds];
[self.navigationController.view addSubview:myView];
If you want to disable interaction with the navigation bar :
[self.navigationController.navigationBar setUserInteractionEnabled:NO];
You could take a look at adding another UIWindow above your root window.
when I tried doing the navigationController.view addSubview, it wouldn't cover my tab bar so I did the following with my app delegate's window:
[self.window addSubview:myView];
if you need access to your appDelegate from another class, you'd just import your application delegate and call it from that.

What is the best method for creating a layer to catch touch events?

I need to put up an info screen above the main interface, but I need it to be alpha'd so you can see the interface underneath it. However, when I touch across the screen, the interface underneath is still running.
What is the best method for intercepting the touch events so they don't pass through? I tried to add a custom UIButton the size of the screen, but that didn't work either :(
There is too much code to post here unfortunately. The view is hundreds of lines long, but the important bit is adding the overlayed subview, which is like this:
InfoScreen *infoScreen = [[UIView alloc] initWithFrame:self.view.frame];
UIButton *invisibleButton = [UIButton buttonWithType:UIButtonTypeCustom];
invisibleButton.frame = self.view.frame;
[self.view addSubview:invisibleButton];
[self.view addSubview:infoScreen];
I am using touchesBegan, touchesMoved, touchesEnded and touchesCancelled in the view below. Is this possibly why the touches are getting through?
Thanks!
:-Joe
If you want to stop everything from responding (for example for a time-based block), you can use
[[UIApplication sharedApplication] beginIgnoringInteractionEvents];
and
[[UIApplication sharedApplication] endIgnoringInteractionEvents];
It won't work if you need a touch to cancel this state ;-). In that case, a transparent UIView on top of your background will get the job done. If it doesn't, post some code.