I have found several questions on this but haven't really seen a great answer as to how to do it other then using a delegate. I came up with a solution that works quite nicely however I'm not sure if it would be bad in the long run.
Here is my solution which thus far has performed fantastically. If anyone can tell me why this would be a bad way to implement this please let me know!
[self dismissViewControllerAnimated:NO completion:^(){
[[[[UIApplication sharedApplication] keyWindow] rootViewController] presentViewController:vc animated:NO completion:nil];
}];
That's the proper way to do this. In fact Apple introduced the completion blocks since iOS 5.0 especially for this kind of purposes.
Why would you want another way if the current way is simple and makes total sense?
Related
i've been searching around the web but couldn't find an answer.
basically i wanna take two photos one right after the other.
i'm using UIImagePickerController to show a picker and implementing didFinishPickingMediaWithInfo.
when it gets called i'm checking my count so that if its one, i implement a block and pass it to dismissViewControllerAnimated like this:
if(1 == count) {
void (^simpleBlock)(void);
simpleBlock = ^{
[self useCamera];
};
[self dismissViewControllerAnimated:NO completion:simpleBlock];
}
it all seems to work fine, and even the useCamera method is called.
the problem is that the second time the picker shows i see all of its controls but i don't see on the screen the image from the camera.
any help would be appriciated.
i managed to work it out with replacing the call to useCamera with:
[self performSelector:#selector(useCamera) withObject:nil afterDelay:0.3];
i think my question has some relation to: iOS 7 UIImagePickerController has black preview
since the delay fixed the problem.
For you to save time. You can use available library out there. These are my good choices. CTAssetsPickerController ELCImagePickerController
UIImagePickerController helps to access the default camera app in iOS.
It will allow only limited functionalities like take picture/video, photo album.
I'm using GCD to make sure this happens on the main thread, but even that doesn't fix the issue.
- (void)showCat:(NSNotification *)notification {
dispatch_async(dispatch_get_main_queue(), ^{
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:#"Main" bundle:nil];
UINavigationController *navVC = [storyboard instantiateViewControllerWithIdentifier:#"Cat"];
[self presentViewController:navVC animated:YES completion:^{
//this never happens on iOS7
}];
});
}
navVC is not nil.
Works fine on iOS8. On iOS7 the app just hangs. Memory usage continuously goes up until it crashes due to memory pressure.
What else could be the cause of this? presentViewController works fine in other areas of the app. This code is called when a notification is received.
Actually turned out there was some recursive code in viewDidLayoutSubviews of the presented view controller. Thanks to #matt for the tip. Not sure why this isn't also an issue in iOS8, but nevertheless the problem is fixed.
Goes to show that actually offering advice even if you don't have the entire code base of the project in front of you can still be helpful, rather than simply downvoting from your high horse.
While the following line works on iPhone 7.1/8.1, on iPad it only works on 7.1. On 8.1 the memory usage goes up and up until it crashes:
[self.navigationController pushViewController:detailController animated:YES];
This line happens here:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
OBDialogDetailViewController* detailController = [[OBDialogDetailViewController alloc] initWithOption:(OBSelectionFilterOption*)option];
[self animateChangeForView:nil atIndexPath:indexPath toRect:CGRectMake(0, 0, 0, 0) andNewHeight:0];
if (self.navigationController)
{
[self.navigationController pushViewController:detailController animated:YES];
}
}
Since I just got responsible for this application, thas has grown over years and has no documentation, I'm a little bit desperate. I searched and tried multiple answeres and solutions for two days now.
Please tell me what more information I can provide.
It will not happen in all scenarios. But couple of things I would like to mention :
I was trying to play an encrypted video (heavy file) on the destination viewcontroller of UINavigationController. Method which decrypts and loads the video on that viewcontroller's view takes time when I load it in viewDidLoad. In that case, please use the following code.
[self performSelectorInBackground:#selector(createVideoPlayer) withObject:nil];
[self performSelectorInBackground:#selector(createVideoPlayerControllerView) withObject:nil];
Please refer this link to manage memory issues even if you are using ARC.
This might not answer your question directly, but will certainly help you to debug. Please post whatever solution you get. Thanks.
I am looking for some advice as to the best way to handle this situation:
In my appDelegate I call registerForRemoteNotificationTypes in didFinishLaunchingWithOptions as follows:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Let the device know we want to receive push notifications
[[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeSound | UIRemoteNotificationTypeAlert)];
[[self window] setBackgroundColor:[UIColor blackColor]];
[self.navigationController setNavigationBarHidden:YES];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];
return YES;
}
However, I need to wait for a device token to be returned before my app can continue, so I was wondering what the best place to wait for this before continuing? Currently my viewDidLoad gets called, but I sometimes have failures because the device token did not come back yet.
I was thinking that I could move my code from viewDidLoad to myViewDidLoad and was hoping I could wait for a notification that would happen once I receive the device token and then call myViewDidLoad.
But, I am not sure where to set the notification. I know this is a basic question, but I am still learning iOS.
Any suggestions would be most helpful.
You don't wait. Never, never wait.
When dealing with asynchronous stuff like networking (as here), you must write your app in such a way that it can proceed in some way even if the networking hasn't happened yet. It's that simple.
Your second impulse is much more correct. When you get the remote notification in the app delegate (I'm assuming), the app delegate can talk to the view controller in question and give it the new info and tell it to update itself (and the view controller can then update the view to display whatever needs displaying at that point).
Since you know you're going to need to do this, you need to set up "lines of sight" communication in advance. You have all the pieces of the puzzle in your hands in the app delegate, so you can arrange to hang on to a reference to that view controller, for when you'll need it later.
I posted a comment to my question with my solution. Not ideal, but it works for now.
I am using a UIActivityViewController to implement image sharing.
UIActivityViewController *shareVC = [[UIActivityViewController alloc] initWithActivityItems:#[image] applicationActivities:nil];
[shareVC setCompletionHandler:^(NSString *activityType, BOOL completed){
NSLog(#"completed image export activity: %# - %d", activityType, completed);
}];
[self presentViewController:shareVC animated:true completion:nil];
In testing, I have noticed that if the user selects, for example, "Assign to Contact", but then denies the permission in the ensuing dialog, then they are taken to a screen that says "This app does not have access to your contacts. You can enable access in Privacy Settings.", from which there is no way to back out. The only way for them then to get back to the actual app is to manually restart it.
I'm fairly happy to leave this behaviour as is for now since I don't anticipate any users will be particularly bothered by it, but I'd like to know if there is a sensible way to work around it, and if it is indeed the expected behaviour.
Hmm, maybe you could check if a segue is called when the new "This app does not have access to your contacts. You can..."-Viewcontroller is shown. Then you could manipulate the destinationViewController property of the segue and add for example a button, with an action enabling the user to go back.
All highly theroretical.
I am working on the iPad platform, and in that context presenting a UIActivityViewController directly is wrong according to the documentation, which states that
When presenting the view controller, you must do so using the appropriate means for the current device. On iPad, you must present the view controller in a popover. On iPhone and iPod touch, you must present it modally.
In most ways, the behaviour of the modally presented view controller on iPad seemed perfectly fine, but this case illustrates why it is not appropriate. I don't know how the equivalent case is handled on iPhone / iPod touch as I haven't really looked at those platforms just yet.
Now that I am presenting it in a UIPopoverController, the view explaining that the app doesn't have access to contacts appears within the popup, and is dismissed as the popup is dismissed. Unfortunately it appears that the completion handler is not called in this case; I'm not sure if that's an iOS bug or if I lack understanding of something. It is a slight problem for me at the moment, so I'll have to work around it.
Unfortunately, it seems relatively unlikely that anyone experiencing a related problem will be helped by my question / answer; maybe I'll try to edit the question.