I want to replace the title and message with the return values from a different class and also put it into an if statement that will see if the return value matches a value i state. can you help me out a little bit, this is my code below, I'm using theos by the way
the 3 methods i want to get the values for are
-(id)title
-(id)message
-(id)_appName
from the SBBulletinBannerItem class
any help is appreciated
%hook SBBulletinBannerController
- (void)_handleBannerTapGesture:(id)reply
{
reply = [[UIAlertView alloc] initWithTitle:#"title" message:#"message" delegate:self cancelButtonTitle:#"Close" otherButtonTitles:#"Reply", nil];
[reply show];
[reply release];
}
%end
It sounds like you'll want to use delegates and protocols. You may have seen this using standard Cocoa and Cocoa Touch classes. This is how you respond to events in a UITableView.
You can find examples of implementing this yourself here.
Related
I'm trying to create a text box with multiple fields, but I'm having trouble getting the second to show (as a matter of fact, when I type the second field in, it causes my text box not to show up all together.)
Here's what I have:
-(IBAction)popupCheckIn {
//UIAlertView *alertCheckIn = [[UIAlertView alloc] initWithTitle:#"Check in" message:#"Please fill out the following to check in." delegate:self cancelButtonTitle:#"Check in." otherButtonTitles:#"Cancel.", nil];
//[alertCheckIn show];
UIAlertView * alert =[[UIAlertView alloc ] initWithTitle:#"Check in" message:#"Please fill out the following fields to check in." delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles: nil];
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
UITextField * nameField = [alert textFieldAtIndex:0];
nameField.keyboardType = UIKeyboardTypeDefault;
nameField.placeholder = #"Your Name";
alert.alertViewStyle = UIAlertViewStylePlainTextInput;
UITextField * hostField = [alert textFieldAtIndex:1];
hostField.keyboardType = UIKeyboardTypeDefault;
hostField.placeholder = #"Host Name";
[alert addButtonWithTitle:#"Check in."];
[alert show];
When I run this code, I get an error that says "Thread 1: signal SIGABRT" and my pop up won't come up at all; when I have just the name field, it works fine.
What am I doing wrong with my second text field? Thanks!
I think that your error arises because that type of UIAlertView doesn't contain more than one UITextField, and when trying to access the second it raises a NSRangeException. This is according to the docs.
https://developer.apple.com/library/ios/documentation/uikit/reference/UIAlertView_Class/UIAlertView/UIAlertView.html#//apple_ref/occ/instm/UIAlertView/textFieldAtIndex:
I tried your code, the entire error message is:
2014-06-26 17:13:56.213 Testing1[2444:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'textFieldIndex (1) is outside of the bounds of the array of text fields'
The issue, is that you only have ONE UITextField with the UIAlertViewStyle set to UIAlertViewStylePlainTextInput. So this part of code ([alert textFieldAtIndex:1] is causing the crash).
Repeating the line alert.alertViewStyle = UIAlertViewStylePlainTextInput; won't create a new one.
The only way to get 2 UITextFields, is to use the UIAlertViewStyleLoginAndPasswordInput UIAlertViewStyle.
A way could be then to set the second one (like the first one) is like this:
[hostField setSecureTextEntry:FALSE];
But personally, I think that I don't recommend it. It may be blocked in the future.
Since we cannot custom really the existing UIAlertView since iOS7 (can't add subview), I'd suggest you create (or find in CocoaControls/GitHub) your own CustomAlertView-like.
You'll want to use alert with the alert style UIAlertViewStyleLoginAndPasswordInput. See this answer: UIAlertView with Two TextFields and Two Buttons
I've an observer pattern on the UI that checks what's the status of an object that handles a server connection that's trying to update a certain field on a database.
The UI's update method receives an object containing data pairs containing the information of what's happening with the connection. The problem is that I'm getting tangled with a lot of ifs checking for different possibilities.
- (void) update:(Bundle *)arg
{
if ([[arg getData:#"updatee"] isEqualToString:#"email"]){
UITableViewCell *emailCell = [[self tableView] cellForRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:0]];
if ([[arg getData:#"connecting"] isEqualToString:#"true"]) {
//Email is being posted
[_emailLabel_email setText:#"Connecting..."];
[_emailLabel_set setHidden:YES];
emailCell.accessoryType = UITableViewCellAccessoryNone;
[_emailActivityIndicator startAnimating];
}else{
if ([[arg getData:#"succesfull"] isEqualToString: #"false"])
//Email was posted unsuccesfully
[[[UIAlertView alloc] initWithTitle:#"Taken Email Address"
message:#"The email address that you entered is already in use, please double check it"
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil] show];
else{
//Email was posted succesfully.
[_emailLabel_set setText:#"Change"];
}
[_emailActivityIndicator stopAnimating];
[_emailLabel_email setText:[mng getEmail]];
[_emailLabel_set setHidden:NO];
emailCell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
}
//Password cases
}
}
As the server responds with a string I'm finding difficult to avoid this spaggetti of code.
Which would be the smarter object to send on the update method?
You could keep the data how it is and put all of the values you expect for [arg getData:#"updatee"] as the keys in a dictionary. The values would be the string representation of method selectors, where each of the methods handles one of the cases in your current if statement. Now your update: method just gets the selector string from the dictionary, converts it to a real selector (NSSelectorFromString) and calls the method (passing the arg as a parameter, all methods used here must have matching parameter listing). If you receive an unexpected update type nothing would happen so you should log / assert that. If you get an exception while translating the selector you probably have a typo (good candidate for a test which executes all of the methods in the configuration).
Of course you could basically do the same thing with all the methods and a dirty big if / else statement.
I am new to iOS, and still learning the proper ways of how to do things. Another question that just reared its head, how can I cease execution of a method, based on a conditional and return back to calling code? Normally in PHP, I simply return true/false, or throw an exception, rather than tucking huge blocks of code within nested conditionals, but in iOS, I am not allowed to return from a method with a IBAction return signature.
What would be the preferred way of handling this sitch?
- (IBAction)submitCode:(id)sender
{
if ([codeEntry.text length] == 0) {
UIAlertView *message = [[UIAlertView alloc] initWithTitle:#"Form Validation" message:#"No code entered, please try again."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[message show];
// IOS not allowing this
return NO;
}
// Prefer not to wrap the rest of the logic in an else, rather just cease
// execution and return back to calling code
NSLog(#"I would have submitted!");
}
You need to call return;, not return NO;.
The IBAction is really void. This means the method has no return value.
Just use
return;
This will stop execution of the current method.
Since IBAction is secretly typdef'ed to void, you can't return anything. Nothing is nothing is nothing, so just use return;.
Here is my code that calls "displayAlert". The problem is not only do I get an error message (wait_fences: failed to receive reply: 10004003) but the "alert" is displayed twice!
if(gSiteID.globalSiteID.length == 0) { // user didn't choose site
[self displayAlert:NSLocalizedString(#"Missing Site ID", nil) andData:NSLocalizedString(#"You must choose a site from the View Sites page",nil)];
return;
}
This the code for "displayAlert":
- (void) displayAlert: (NSString *) title andData: (NSString *) errorMsg {
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle: title
message: errorMsg
delegate:nil
cancelButtonTitle: #"OK"
otherButtonTitles: nil];
[alert show];
return;
}
I have searched SO and Google and found nothing that is specific to my issue. What am I doing wrong?
Are you testing this on a real device or the simulator? wait_fences: failed to receive reply usually means something bad happened with the debugger's connection to your device, or that you sat at a breakpoint for a really long time and it timed out. Are you sure that the code only executes once, and that nothing else could call that method? Stick breakpoints in your if statement and in your displayAlert:andData: method and see what happens. Run through your logic and find all the cases when that display alert method can be called and stick breakpoints on all of them.
I found the problem: indeed I was calling it twice from different .cs files (do you see the egg on my face?). Jack Lawrence please post your answer to the question, since you hit it on the head.
I'm trying to write some generic http response handler functions that sometimes open UIAlertViews.
These generic handlers are class methods don't have knowledge of their callers (at the moment).
But I'm facing an obvious problem about how to alloc/dealloc the UiAlertView delegate object.
e.g.
MyAlertViewHandler* alertHandler = [[MyAlertViewHandler alloc] init];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:msg message:nil delegate:alertHandler cancelButtonTitle:TEXT_NEVERMIND otherButtonTitles:TEXT_RESET_PASSWORD,nil];
[alert show];
[alert autorelease];
There's an obvious memory leak there cos I'm alloc'ing and not release it anywhere.
So, where do I "hang" MyAlertViewHandler such that I can release it to avoid the memory leak?
One idea is to tell the caller there's a NSObject that needs to be released and give responsibility back to the UIViewController - but is there another way?
I hope my question is clear enough.
In your alertView:didDismissWithButtonIndex: delegate method (in your MyAlertViewHandler) you could simply [self release]; or [self autorelease]; as the very last command.