I have a block completion being called from within a button press message and, depending on state, optionally a UIAlertView being displayed. However, when invoked the UIAlertView appears three (3) times...
With the full information but it disappears itself and shows
Just the title shows and when I click OK
Appears again with full information (as in #1) for which I have to dismiss again
Following is a snippet of the code:
[credential performDataOperation:[credential commandForCreateOnClass:self.className]
withArguments:edits
completionBlock:^(BOOL succeded, id before, id after, NSDictionary *arguments, NSError *error) {
if (succeded) {
self.object = after;
self.objectWasCreated = YES;
[self prepareEditsDictionary];
self.navigationItem.rightBarButtonItem.enabled=NO;
}
else {
errorRecieved = YES;
[[[UIAlertView alloc] initWithTitle:#"Error" message:#"Error Message" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil] show];
}
}];
You are probably seeing just two alerts. The first appears, but you also have code somewhere that summons the second, so it overrides the first. Then you dismiss the second and the first returns. You need to hunt for your code that presents the second alert, the one without the message, and figure out why that code is running. Just do a global search in your project for UIAlertView! It must be in there somewhere, because all alert views are created and presented in code.
You may have accidentally hooked up your button so that it has multiple action handlers. Of course I could be wrong, but this is a mistake I've sometimes made, and then I've been mystified why my method was being called twice or some unwanted extra thing was happening when I tapped the button. Check your nib/storyboard or code to make sure. The fact that a single button can have many actions for a single UIControlEvent is very surprising and is almost never used intentionally.
(If that's not the right answer, then perhaps the solution lies in your performDataOperation method, whose code you do not show. Maybe it calls the simpler UIAlertView, in addition to calling the block.)
Related
I'm working on an iOS app that uses a tab bar. An item is scanned using a barcode reader, and a callback method sets the tab bar item to the result view, then sends the request to the server. The callback from the server populates the display and the result view is shown.
However, under certain conditions which depend on the response from the server, I'd like show an alternate view which allows the user to manually enter the data, and then process the data in the same way as the callback. The manual entry display can't be shown on the tab bar.
So I create a modal view and exit the callback:
EnterTextController* enterTextController = [[EnterTextController alloc]init];
presentModalViewController:enterTextController animated:YES];
return;
In the view, I take the input and call the same process called by the callback:
NSLog(#"Button Clicked!");
NSString *myText = myInput.text;
[self dismissViewControllerAnimated:NO completion:nil];
[self.mainViewController processMyText: myText];
The problem is the processMyText doesn't get executed. I have a breakpoint set and it never hits it.
I'm sure I'm not going about this correctly. Any suggestions would be welcome.
Make sure the receiver isn't nil.
I would like to wait saveInBackground Parse method before the view disappears. Because the view following is using this data, but that doesn't have the time to refresh...
Here is my code :
-(void) viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
PFQuery *urlImage = [PFQuery queryWithClassName:#"urlImage"];
[urlImage whereKey:#"objectId" equalTo:#"IcK6mFChL7"];
[urlImage getFirstObjectInBackgroundWithBlock:^(PFObject *urlImageParse, NSError *error) {
if (!error) {
[urlImageParse setObject:self.photoURL.text forKey:#"URL"];
[urlImageParse saveInBackground];
} else {
NSLog(#"Error: %#", error);
}}];
}
Can I make this code in other place that viewWillDisappear:? Or maybe use MBProgressHUD?
viewWillDisappear is a place to execute code, knowing that the view is about to disappear. I believe what you are looking to do is run some action, prior to the view actually going away.
This part right here -> [urlImage getFirstObjectInBackgroundWithBlock:^
means that the code inside that block is going to run on a different thread. So what you are currently saying is, when the view is about to disappear, spin off this other thread and save something in the background, but continue on doing whatever you need to do, like make this view disappear. That's what you're telling the system. So it continues on, doing what it was going to do, not caring about the results of saving that object.
There is a reason that your view is about to disappear. Something happened in your app where the system is thinking it needs to close this view and present another one. It could be that you hit a back button, it could be that you clicked a save button, and at the end of that code, you are asking the system to pop this view off the stack. We really don't know with only the code you posted. What we can assume though, is whatever action was taken to make this view disappear, is where you should be trying to save this object, and you should probably be waiting for a response before you leave this view. If the next view is dependent on that information, then it doesn't make sense to dismiss this view, and present the next one, until you get a successful response that this object was saved. This is just an assumption though, since I don't understand what your app is doing or what is going on when you are trying to save this data, and what the next view looks like. I would say that typically, if you need this stuff to be saved, in order to continue on in your app, you should be saving this data and waiting for a response, to either display an error message to the user, or if successful, then move on to the next screen.
I'm using a UIPageViewController to handle data entry where the last page is the active record and the previous pages are old records that can't be edited. So I need a way to verify that the user wants to leave the last page while allowing all of the other pages to navigate as usual.
Ideally I could really use a -(BOOL)pageShouldTurn method but that doesn't exist.
Does anyone know of a way to detect if a page is about to unload then stop the page turn based on some condition? I'm not having any luck with the gesture recognizer methods as they don't seem to be triggered even when the delegate is set.
Thanks to Michael, I've added this to my pageViewController which does exactly what I needed:
-(void)pageViewController:(UIPageViewController *)pvc willTransitionToViewControllers:(NSArray *)pendingViewControllers
{
if ([pvc.viewControllers.lastObject pageIndex] == [self.pageDataSource.allObjects count]) {
UIAlertView *alertDialog;
alertDialog = [[UIAlertView alloc]
initWithTitle:#"Are You Done?"
message:#"Once you leave this page you can't edit this record again"
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[alertDialog show];
}
}
So the alert box stops the page from turning only once. When it is dismissed, the user can then change the page. My version checks to make sure this only happens on the last page, you could remove the 'if' statement and alert on every page turn, but that would be annoying.
Seems to me there are at least two options.
Number one, you have "- (void)pageViewController:(UIPageViewController *)pageViewController willTransitionToViewControllers:(NSArray *)pendingViewControllers". You might be able to catch a transition there and deny / force the old page to be reset.
Or, you can now subclass "UIPageViewController" and in your subclassed controller, you can define a new delegate protocol (incorporating all the original UIPageViewControllerDelegate" methods) and you can add your own "-(BOOL) pageShouldTurn" protocol method.
Both of these possibilities require iOS 6.
In controller on different actions I need to show UIAlertView with "OK" and "CANCEL" buttons, and every "OK" click on those 5 UIAlertViews need to do different things. Is possible to declare something like lambda function to specify what "OK" button from each UIAlertView is going to do? (In code on 5 places I have with different questions and messages and actions on ok, some don't have text for input at all)
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Apply"
message:#"Are you sure you want to apply ?"
delegate:self
cancelButtonTitle:#"CANCEL"
otherButtonTitles:#"OK",
nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
[alert show];
(At the moment I remember action which cause UIAlertView to show and then based on action I do different things, but it is not clear code).
Use a category called UIKitCategoryAdditions that implements a block-based UIAlertView and UIActionSheet for the selection or cancel actions.
It makes it super simple to assign actions to many user prompts without having to implement the delegate methods and deal with handling more than one object's delegate response in the same controller.
It's possible, but by extending the existing controls. I would recommend using RIButtonItem, I'm using it myself in the latest couple of my projects.
Use an objective-c block in lieu of your delegate.
delegate: ^(UIAlertView * alertView, NSInteger buttonIndex) { doSomethingHere; };
So I have a label, and when I click on it, I want it to show sort of a table in an "alert" type pop-up window that allows you to scroll (since there will be quite a few lines of data) through values like this:
1) some value : correct
2) Some other value : incorrect
The data I have is stored in two different NSMutableArrays.
I know I can make an alert show with some code like this,
UIAlertView *message = nil;
message = [[UIAlertView alloc] initWithTitle:#"Definition"
message:definition
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
Is it possible to do this? If so, what should I look at?
Thanks
It will be a very bad solution - why not use modal controller instead?
Anyway, you can always add a subview to UIAlertView. However, note that changing its size could be complicated.