I have a simple question with no answer.
I have a UIAlertView local variable like this,
- (void)insertNewObject:(id)sender
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"title"
message:#"message"
delegate:nil
cancelButtonTitle:#"cancelButtonTitle"
otherButtonTitles:#"otherButtonTitle", nil];
[alert show];
}
When I execute the - (void)insertNewObject:(id)sender method, every time the reference count of the UIAlertView is increased one by one and they are not discarded.
So, any issue is on this with ARC. I need to keep the living objects count without increase while I execute the - (void)insertNewObject:(id)sender method.
Related
i have an error which i donno how to fix it it's making me crazy. i have searched about the solution a lot but didn't find anything which works here .
here is the code and you can see the error in the picture .
thanks
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:[NSString stringWithUTF8String:title]
message:[NSString stringWithUTF8String:body]
delegate:nil
cancleButtonTitle:[NSString stringWithUTF8String:cancleLable]
otherButtonTitles:[NSString stringWithUTF8String:firstLable],
[NSString stringWithUTF8String:secondLable], nil];
[alert show];
I've just started trialling CloudKit and am having some pretty slow query times. Here is some sample code I am using:
//CLOUDKIT
CKContainer *container = [CKContainer defaultContainer];
CKDatabase *privateDatabase = [container privateCloudDatabase];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"TRUEPREDICATE"];
CKQuery *query = [[CKQuery alloc] initWithRecordType:#"FlightLog" predicate:predicate];
[privateDatabase performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) {
//SUCCESS
if (!error)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"SUCCESS" message:#"IT WORKED" delegate:self cancelButtonTitle:#"dismiss" otherButtonTitles:nil];
[alert show];
NSLog(#"%#", #"fetchFlights success!");
NSLog(#"%#", self.fetchedRecords);
self.fetchedRecords = results;
[self.tableView reloadData];
}
//ERROR
else
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"error" message:error.localizedDescription delegate:self cancelButtonTitle:#"dismiss" otherButtonTitles:nil];
[alert show];
NSLog(#"%#", error);
}
}];
I get the private database, and query for all records. There is just four simple ones I added in the dashboard.
Upon calling this code, I can see from my console log that the success message gets called almost immediately, with a null results array. Then moments later, the results are returned, as seen in the log. However, the alert view isn't shown and results displayed in my table for about 3-4 more seconds.
What's going on?
This is resolved. As Edwin mentions, I didn't know that the callback is on a background thread. So when I call [self.tableView reloadData] in the completion block, it is also running on the background thread.
By putting it back on the main thread, the table view reloads within about a second. Vs taking about 4-5 seconds if running on the same thread as the callback.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^{
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
});
Let me know if I have misunderstood, but I think that's what has happened.
I've got a simple UIAlertView showing when user runs the app. It has this structure:
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Welcome!", "")
message:NSLocalizedString(#"This is a welcome message.", "")
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[alert show];
[alert release];
The question is, How can I customize it to show every 5 runs for example?
Thanks in advance ;)
You can use NSUserDefaults to store app executions count for key AppRunCount (you can introduce your own key name):
int runCount = [[NSUserDefaults standardUserDefaults] integerForKey:#"AppRunCount"] + 1
[[NSUserDefaults standardUserDefaults] setInteger:runCount forKey:#"AppRunCount"];
if (runCount <= 5) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Welcome!", "")
message:NSLocalizedString(#"This is a welcome message.", "")
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles: nil];
[alert show];
[alert release];
}
You can just add code above to viewDidLoad
There will be a method in AppDelegate class like
- (void)applicationDidBecomeActive:(UIApplication *)application
Now create one NSUSerdefaults in this method and make one integer and increment that integer and save it in NSUserdefaults
Now every time application starts that method will be called and integer will incremented
Now make if condition in that method like below
if(your integer which has nsuserdefaults >=5)
{
your alertview
again here make your nsinteger to Zero which is stored in nsuserdefaults
your integer which has nsuserdefaults =0
}
This is the answer of your second question,Every after 5 times app run. alert will be pop up
Let me know it is working or not..!!!!
Happy Coding!!!!
Having some issues with the ... in ObjectiveC.
I'm basically wrapping a method and want to accept a nil terminated list and directly pass that same list to the method I am wrapping.
Here's what I have but it causes an EXC_BAD_ACCESS crash. Inspecting the local vars, it appears when otherButtonTitles is simply a NSString when it is passed in with otherButtonTitles:#"Foo", nil]
+ (void)showWithTitle:(NSString *)title
message:(NSString *)message
delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
message:message
delegate:delegate
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:otherButtonTitles] autorelease];
[alert show];
}
How do I simply siphon from the argument incoming to the argument outgoing, preserving the exact same nil terminated list?
You can't do this, at least not in the way you're wanting to do it. What you want to do (pass on the variable arguments) requires having an initializer on UIAlertView that accepts a va_list. There isn't one. However, you can use the addButtonWithTitle: method:
+ (void)showWithTitle:(NSString *)title
message:(NSString *)message
delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
message:message
delegate:delegate
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:nil] autorelease];
if (otherButtonTitles != nil) {
[alert addButtonWithTitle:otherButtonTitles];
va_list args;
va_start(args, otherButtonTitles);
NSString * title = nil;
while(title = va_arg(args,NSString*)) {
[alert addButtonWithTitle:title];
}
va_end(args);
}
[alert show];
}
This is, of course, very problem-specific. The real answer is "you can't implicitly pass on a variable argument list to a method/function that does not have a va_list parameter". You must therefore find a way around the problem. In the example you gave, you wanted to make an alertView with the titles you passed in. Fortunately for you, the UIAlertView class has a method that you can iteratively call to add buttons, and thereby achieve the same overall effect. If it did not have this method, you'd be out of luck.
The other really messy option would be to make it a variadic macro. A variadic macro looks like this:
#define SHOW_ALERT(title,msg,del,cancel,other,...) { \
UIAlertView *_alert = [[[UIAlertView alloc] initWithTitle:title message:msg delegate:del cancelButtonTitle:cancel otherButtonTitles:other, ##__VA_ARGS__] autorelease]; \
[_alert show]; \
}
However, even with the variadic macro approach, you'd still need a custom macro for each time you wanted to do this. It's not a very solid alternative.
How about constructing an NSInvocation object? Since arguments must be passed by pointer, you could pass the pointer to the nil-terminated list.
You could also iterate over the parameters using marg_list() and construct a nil-terminated list yourself.
These are just simple suggestions; I haven't tried them out.
This is specific to the OP's UIAlertView-wrapping case, and tested only on iOS7: It appears that once a UIAlertView has been initialised with otherButtons:nil, and then has its style set to UIAlertViewStylePlainTextInput it doesn't call its delegate's alertViewShouldEnableFirstOtherButton: to validate input. I'm not sure if this is a bug or intended behaviour but it broke my principle of least astonishment. This is reproducible with the following (I'll assume the delegate's alertViewShouldEnableFirstOtherButton: is implemented):
UIAlertView *av = [[UIAlertView alloc] initWithTitle:#"Title"
message:#"message"
delegate:self
cancelButtonTitle:#"Cancel"
otherButtonTitles:nil];
[av setAlertViewStyle:UIAlertViewStylePlainTextInput];
[av addButtonWithTitle:#"OK"];
[av show];
The solution, since UIAlertView happily accepts otherButtons:nil, is to initialise UIAlertView with otherButtonTitles (which can be nil), and iterate over the variadic arguments, as above:
+ (void)showWithTitle:(NSString *)title
message:(NSString *)message
delegate:(id)delegate
cancelButtonTitle:(NSString *)cancelButtonTitle
otherButtonTitles:(NSString *)otherButtonTitles, ...
{
UIAlertView *alert = [[[UIAlertView alloc] initWithTitle:title
message:message
delegate:delegate
cancelButtonTitle:cancelButtonTitle
otherButtonTitles:otherButtonTitles] autorelease];
// add your [alert setAlertViewStyle:UIAlertViewStylePlainTextInput] etc. as required here
if (otherButtonTitles != nil) {
va_list args;
va_start(args, otherButtonTitles);
NSString * title = nil;
while(title = va_arg(args,NSString*)) {
[alert addButtonWithTitle:title];
}
va_end(args);
}
[alert show];
}
my application is running fine in simulator...but not on real device....and i have jailbroken iphone so i am unable to debug through device...if i use try catch something like this
#try
{
Statements
}
#catch (NSException *ex) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"%#",ex]
delegate:self cancelButtonTitle:#"OK" otherButtonTitles: nil];
[alert show];
}
will my application show error on alertview before crashing?
if not how could i find where is the bug?
Catching the exception means you are doing something in response to this "error" coming about and it wont crash the application , thats the point of catching exceptions-to tell how to handle cases where errors arrise so your app wont crash, so yes the alert view will show...
That will work so long as your #catch block doesn't throw any exceptions while trying to build the UIAlertView. Make sure you release or autorelease it, and support the UIAlertViewDelegate protocol.
Try this:
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:[ex name]
message:[ex reason]
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles: nil];