I am using a UIView to show busy/processing clue to User and components in loading view are not responding to user touches. Let me elaborate my problem.
I have around 3 UIViewControllers and based on situation one View from VieControllers would be displayed. I use following code to change current view
UIView *currentView = self.view;
UIView *theWindow = [currentView superview];
//Some other code
[currentView removeFromSuperview];
[self.view setFrame: [tileCountViewController.view bounds]];
[theWindow addSubview:tileCountViewController.view];
[theWindow setFrame:[tileCountViewController.view bounds]];
[theWindow setFrame: [[UIScreen mainScreen] bounds]];
I then have a Loading view which generally used to show busy/processing kinda of UI to User. I created Loading view in following way from nib file
- (id)init {
UIDeviceOrientation orientation = [UIDevice currentDevice].orientation;
NSString *nibName = #"LoadingViewController";
if(UIInterfaceOrientationIsLandscape(orientation)) {
nibName = #"LoadingView-landscape";
}
else {
nibName = #"LoadingView";
}
UINib *nib = [UINib nibWithNibName:nibName bundle:nil];
UIView *portraitView = [[nib instantiateWithOwner:self options:nil] objectAtIndex:0];
self = [super initWithFrame:portraitView.frame];
[self addSubview:portraitView];
[self bringSubviewToFront:portraitView];
return self;
}
In app delegate, I initialize loading view and add it to Main window
if(!loadingViewIndicator){
loadingViewIndicator = [[LoadingView alloc]init];
}
[[[UIApplication sharedApplication]keyWindow]addSubview:loadingViewIndicator];
loadingViewIndicator.hidden = YES;
Whenever I need to show loading/busy view, I simply load it like this
[loadingViewIndicator performSelectorOnMainThread:#selector(startLoadingViewIndicator:) withObject:startMsg waitUntilDone:NO];
- (void)startLoadingViewIndicator:(NSString *)startMsg{
self.hidden = NO;
[self.superview bringSubviewToFront:self];
[self.activityIndicator startAnimating];
[self.loadingMessage setText:startMsg];
self.loadingProgressView.progress = 0.0f;
[self refreshPosition];
}
Everything works fine but components in Loading view are not responding to touches. Any clue what is going wrong?
I just realized that problem is due to threading issue. I show this subview when User starts downloading any file. My earlier code was to directly start download
urlconnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately: YES];
I am now calling this method from another method using background thread as below
[self performSelectorInBackground:#selector(startDownload) withObject:nil];
And then I am adding runloop in download like
urlconnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately: YES];
CFRunLoopRun();
This works fine and my subview is responsive. It really took lots of time. The problem is there is clear code example to help to run download in background thread and at the same time make UI responsive.
Related
I want to know if it is possible to load/present modally a UIViewController with a "free form" size like the image below
I want to load the red one allways on top (allways visible) and interact with the ViewController below (blue one) at the same time.
EDIT: what i want is to show and hide FROM APP DELEGATE a small view controller to controll the music in my app.
I was trying with a xib file with a custom UIViewController as the file owner (see image below). The xib is being showed right the way i want, but the UIViewController associated to it, id doesn't load and i don't know why...
So i thought to do it with a UIViewController free formed but im not making it and i don't know wich is the best way
EDIT2:
With the xib file way i did the next:
In AppDelegate i have a function showPlayer that is called with local notification to show the xib
-(void)showPlayer:(int)tag andObjetoCancion:(NSArray *)objetoCancion
{
ZocaloPlayerViewController *vc = [[ZocaloPlayerViewController alloc] initWithNibName:#"ZocaloPlayerView" bundle:nil];
[vc setObjectoCancion:[objetoCancion mutableCopy]];
if (globals.isPlaying) {
[vc setCambiar:YES];
}else{
[vc setCambiar:NO];
}
//here playerView is a UIView initiated in didFinishLaunchingWithOptions
if (playerView == nil) {
playerView = [[UIView alloc] initWithFrame:CGRectMake(0, self.window.frame.size.height, self.window.frame.size.width, altoPlayer)];
}
//keyWindow is UIWindow
//NSLog(#"Abro view %ld", (long)viewPlayer.tag);
keyWindow = [[[UIApplication sharedApplication] delegate] window];
[keyWindow addSubview:playerView];
[keyWindow bringSubviewToFront:playerView];
NSArray *subviewArray = [[NSBundle mainBundle] loadNibNamed:#"ZocaloPlayerView" owner:vc options:nil];
mainView = [subviewArray objectAtIndex:0];
mainView.translatesAutoresizingMaskIntoConstraints = NO; //This part hung me up
[playerView addSubview:mainView];
//needed to make smaller for iPhone 4 dev here, so >=200 instead of 748
[playerView addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"V:|-0-[mainView]-0-|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(mainView)]];
[playerView addConstraints:[NSLayoutConstraint
constraintsWithVisualFormat:#"H:|-0-[mainView]-0-|"
options:NSLayoutFormatDirectionLeadingToTrailing
metrics:nil
views:NSDictionaryOfVariableBindings(mainView)]];
[UIView animateWithDuration:0.3 animations:^{
playerView.center = CGPointMake(self.window.frame.size.width / 2, self.window.frame.size.height - mitadAltoPlayer);
[self.window layoutIfNeeded];
}];
}
ZocaloPlayerViewController *vc is being instantiated but the viewDidLoad function inside it is not being called.... That is my first problem...
With the UIViewController free formed way i don't know how to do it...
Ok, i solved my problem with this post Loaded nib but the view outlet was not set - new to InterfaceBuilder
(i was missing the UIView outlet)
and i changed my code in the showPlayer function to this:
-(void)mostrarPlayer:(int)tag andObjetoCancion:(NSArray *)objetoCancion
{
ZocaloPlayerViewController *vc = [[ZocaloPlayerViewController alloc] initWithNibName:#"ZocaloPlayerView" bundle:nil];
[vc setObjectoCancion:[objetoCancion mutableCopy]];
if (globals.isPlaying) {
[vc setCambiar:YES];
}else{
[vc setCambiar:NO];
}
if (playerView == nil) {
playerView = [[UIView alloc] initWithFrame:CGRectMake(0, self.window.frame.size.height, self.window.frame.size.width, altoPlayer)];
}
//NSLog(#"Abro view %ld", (long)viewPlayer.tag);
keyWindow = [[[UIApplication sharedApplication] delegate] window];
[keyWindow addSubview:playerView];
[keyWindow bringSubviewToFront:playerView];
[playerView addSubview:vc.view];
[UIView animateWithDuration:0.3 animations:^{
playerView.center = CGPointMake(self.window.frame.size.width / 2, self.window.frame.size.height - mitadAltoPlayer);
[self.window layoutIfNeeded];
}];
}
I've looked at 20+ different posts that are vaguely related to this and haven't been able to find a solution.
What I have is a class which subclasses UIViewController. On this class's loadView method, I'm adding a UIWebView inside of a UIScrollView. The UIWebView has scalesPageToFit set to YES. The problem I'm facing is that it seems like zooms are being multiplied! i.e. When you zoom inside the web view the very first time, everything seems to work properly. When you zoom AGAIN, it seems that it takes your already zoomed version and tries to amplify that by an additional factor. This causes the app to crash. Any thoughts on how to fix this? I think something about the reported zoomScale from the UIWebView is messing things up.
Here's a modified sample code to get an idea of the current implementation:
# This is a UIViewController
#implementation MyViewController
- (void)loadView
{
[super loadView];
self.view.accessibilityLabel = #"MyView";
self.scrollView = [[UIScrollView alloc] init];
self.scrollView.backgroundColor = [UIColor blueColor];
self.scrollView.scrollsToTop = YES;
self.scrollView.translatesAutoresizingMaskIntoConstraints = NO;
[self.view addSubview:self.scrollView];
// constraints removed from sample for readability
self.headerView = [[UIViewController alloc] init];
[self.scrollView addSubview:self.headerView];
self.bodyView = [[UIWebView alloc] init];
self.bodyView.delegate = self;
self.bodyView.scalesPageToFit = YES;
self.bodyView.scrollView.scrollsToTop = NO;
self.bodyView.translatesAutoresizingMaskIntoConstraints = NO;
[self.bodyView.scrollView addObserver:self
forKeyPath:KeyValuePath
options:NSKeyValueObservingOptionNew
context:nil];
[self.scrollView addSubview:self.bodyView];
// other constraints here
}
Any help or feedback would be immensely appreciated.
My code to add a UIImagePickerController:
picker = [[[UIImagePickerController alloc] init] autorelease];
picker.delegate = self;
picker.sourceType = UIImagePickerControllerSourceTypeCamera;
picker.showsCameraControls = NO;
[self displayContentController:picker inView:cameraBoxView];
[self.view sendSubviewToBack:picker.view];
- (void)displayContentController:(UIViewController *)content inView:(UIView *)v {
//Delete the previous instance of the same view controller
for (UIViewController *vc in self.childViewControllers) {
if ([vc isKindOfClass:[content class]]) {
[vc removeFromParentViewController];
}
}
[self addChildViewController:content];
content.view.frame = v.frame;
[self.view addSubview:content.view];
[content didMoveToParentViewController:self];
if ([content isKindOfClass:[CCInnerNavigationController class]]) {
innerNavigationController = (CCInnerNavigationController *)content;
}
}
I have disabled all the device orientations except of portrait. But the image from camera is rotated. How to solve this issue in both iOS 6 and 7.
P.S. I understand that there are a lot of soludions but it seems they are too old because NOTHING of them works.
When you instatiate the UIImagePickerController you must also pass it a delegate. The delegate should be conform to 2 protocols UIImagePickerControllerDelegate and UINavigationControllerDelegate. The second makes possible to add some logic for rotation at runtime, implement this methods accordingly to what you want to achieve.
– navigationControllerPreferredInterfaceOrientationForPresentation:
– navigationControllerSupportedInterfaceOrientations:
I changed the following code:
imgView.image = img;
to:
imgView.image = [UIImage imageWithCGImage:img.CGImage scale:1 orientation:UIImageOrientationRight];
And now it works in both iOS 6 and 7. I don't know how it fixes this bug but it really works. Maybe image picker corrupts the image or image view and this code fixes it by creating a new image instance.
I'm pretty new on iOs programming. And I'm stuck at a (i'm sure) very simple issue.
Don't know what i'm doing wrong...
-My viewDidLoad:
[super viewDidLoad];
CGRect frame = CGRectMake(0, 0, 768, 1024);
UIView *uno=[[[UIView alloc] initWithFrame:frame] autorelease];
UIImageView *mainView = [[[UIImageView alloc] initWithFrame:frame] autorelease];
mainView.image = [UIImage imageNamed:#"photo.jpg"];
[uno addSubview:mainView];
UIView *dos=[[[UIView alloc] initWithFrame:frame] autorelease];
UIImageView *mainViewDos = [[[UIImageView alloc] initWithFrame:frame] autorelease];
mainViewDos.image = [UIImage imageNamed:#"Default.png"];
[dos addSubview:mainViewDos];
//
[self.view addSubview:uno];
//
[self anima:uno:dos];
And my anima method:
-(void) anima:(UIView *)uno:(UIView *)dos{
[UIView transitionFromView:uno
toView:dos
duration:2.0
options:UIViewAnimationOptionTransitionFlipFromLeft
completion:nil];
}
It changes the view but without transition...
Thanks
You can't perform an animation within your viewDidLoad--the view changes you make in there are all executed before the view is actually displayed, which is what you're seeing.
Are you trying to show this animation when the view is first displayed? If so, you can get it to work by putting the animation on a timer. Note that with this approach, you'll also have to refactor your anima method a bit to take a single argument.
In your viewDidLoad:
NSDictionary *views = [NSDictionary dictionaryWithObjectsAndKeys:uno, #"uno", dos, #"dos", nil];
[self performSelector:#selector(anima) withObject:views afterDelay:0.1];
Then change your anima method to:
-(void) anima:(NSDictionary *)views {
[UIView transitionFromView:[views objectForKey:#"uno"]
toView:[views objectForKey:#"dos"]
duration:2.0
options:UIViewAnimationOptionTransitionFlipFromLeft
completion:nil];
}
I have two universal applications... one is giving me an EXC_BAD_ACCESS error when I do this in the app delegate:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
ScrollViewController *vc = [[ScrollViewController alloc] init];
[window addSubview:vc.view]; // EXC_BAD_ACCESS here
[window makeKeyAndVisible];
return YES;
}
I do exactly the same (same code, same scroll view controller class) in my other application and get no errors... my scroll view loads fine.
This problem is driving me insane. Here is the ScrollViewController Implementation:
#implementation ScrollViewController
- (void)loadView {
[super loadView];
UIScrollView *s = [[UIScrollView alloc] initWithFrame:[[self view] bounds]];
NSArray *a = [[NSBundle mainBundle] loadNibNamed:#"JCEKKeyboard" owner:self options:nil];
UIView *v = [a objectAtIndex:0];
[s setContentSize:CGSizeMake(400, 500)];
[s addSubview:v];
[[self view] addSubview:s];
}
Remember that when you add subviews i.e. [someView addSubview:someOtherView], you are adding potentially a whole graph of subviews (the subviews of someOtherView). If someView is visible it will trigger a render on the new graph of the subview you've added. So if any of the subviews in the new graph are not correctly retained, you can get this error. You must test the entire view hierarchy you're adding.
Use the following gdb commands in your console:
To test if an individual object is valid
po [someView description]
To test the subviews of someView
po [someView subviews]
To test individual subviews (for instance the first subview element 0)
po [[someView subviews] objectAtIndex:0]
Finally to test an entire view hierarchy at once
po [someView recursiveDescription]
These commands, especially recursiveDescription, are also very useful for troubleshooting layout issues.
init shouldn't be creating the view, loadView does that. Calling the view getter (vc.view) when view is nil will cause loadView to be invoked.
Read the documentation for loadView, you are using it incorrectly. You should not call super from loadView and you must set the view property in the view controller. You should not invoke the getter for view [self view] from inside loadView, because the getter calls loadView. You are supposed to create the view in loadView and set the view property.
Something like this:
- (void)loadView {
NSArray *a = [[NSBundle mainBundle] loadNibNamed:#"JCEKKeyboard" owner:self options:nil];
UIView *v = [a objectAtIndex:0];
CGRect frame = [UIScreen mainscreen].applicationFrame;
UIScrollView *s = [[UIScrollView alloc] initWithFrame: frame];
[s setContentSize:CGSizeMake(400, 500)];
[s addSubview:v];
self.view = s;
}