iPhone crash log - iphone

do you explain the foollowing crash log......
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIViewController createAddressBookCopy]: unrecognized selector sent to instance 0x5908300'.
what does it mean?
my code is here....
-(NSString *)pathOfFile{
NSArray *paths=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask,YES);
NSString *documentsDirectory=[paths objectAtIndex:0];
//lastName.text=[paths objectAtIndex:0];
return [documentsDirectory stringByAppendingFormat:#"contacts.plist"];
}
-(IBAction)createAddressBookCopy{
UIActionSheet *actionSheet=[[UIActionSheet alloc]
initWithTitle:#"Wanna create a copy of Addressbook?"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:#"Yeah!!!"
otherButtonTitles:nil];
[actionSheet showInView:self.view];
[actionSheet release];
ABAddressBookRef addressBook = ABAddressBookCreate();
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople(addressBook);
CFIndex nPeople = ABAddressBookGetPersonCount(addressBook);
NSMutableArray *masterList = [[NSMutableArray alloc] init];
for (int i = 0; i < nPeople; i++) {
ABRecordRef ref = CFArrayGetValueAtIndex(allPeople, i);
CFStringRef fName = ABRecordCopyValue(ref, kABPersonFirstNameProperty);
CFStringRef lName = ABRecordCopyValue(ref, kABPersonLastNameProperty);
NSString *contactFirstLast = [NSString stringWithFormat: #"%#", (NSString *)lName];
CFRelease(fName);
CFRelease(lName);
[masterList addObject:contactFirstLast];
//[contactFirstLast release];
}
//self.list = masterList;
[masterList writeToFile:[self pathOfFile] atomically:YES];
[masterList release];
}
//creating action sheet
-(void)actionSheet:(UIActionSheet *) actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex{
if (buttonIndex!=[actionSheet cancelButtonIndex]) {
UIAlertView *alert=[[UIAlertView alloc]
initWithTitle:#"Copy creaeted."
message:#"New copy is contacts.plist"
delegate:self
cancelButtonTitle:#"DONE"
otherButtonTitles:nil
];
[alert show];
[alert release];
}
}

Check if your IBAction is connected properly. I think its not connected properly. Check if the declaration of the method in .h file is same.

You have sent the message createAddressBookCopy to a UIViewController object. The app crashed because UIViewController does not have a method of that name.

It means that you have some code that tried to call the createAddressBookCopy method on a UIViewController instance. According to the documentation, no such method exists, hence the crash.

That means that some object in your program trying to send createAddressBookCopy message to UIViewController, but this UIViewController object doesn't implement such method

UIViewController doesn't have a method called createAddressBookCopy. I suspect you have a UIViewController subclass which does have that method, but for some reason you're calling the super class. This sometimes happens if you're using interface builder and don't have your outlets hooked up correctly.

Related

iOS- How to show alertView before code starts

I have the following code:
-(IBAction)showAlertView:(id)sender{
alertView = [[UIAlertView alloc] initWithTitle:#"Atualizando" message:#"\n"delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
spinner.center = CGPointMake(139.5, 75.5); // .5 so it doesn't blur
[alertView addSubview:spinner];
[spinner startAnimating];
[alertView show];
}
-(IBAction)getContacts:(id)sender {
[self showAlertView:(id)self];
ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );
I want to show the alert before the rest of the IBAction begins, but im seeing the alertView only at the end of the IBAction. What am I doing wrong?
EDIT: i have:
-(IBAction)getContacts:(id)sender {
// display the alert view
[self showAlertView:self];
// do the synchronous operation on a different queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );
....
if ([contact length] == 8) {
NSString *first = (NSString*)ABRecordCopyValue(person, kABPersonFirstNameProperty);
NSString *last = (NSString*)ABRecordCopyValue(person, kABPersonLastNameProperty);
NSString *phone = contact;
ContactInfo *user1 = [[ContactInfo alloc] init];
user1.first = first;
user1.last = last;
user1.phone = phone;
user1.person = person;
user1.phoneIdx = j;
user1.book = addressBook;
NSLog(#"phone is %#", phone);
[secondViewController.users addObject:user1];
}
ABRecordSetValue(person, kABPersonPhoneProperty, mutablePhones, &error);
}
}
bool didSave = ABAddressBookSave(addressBook, &error);
if(!didSave){
NSLog(#"error!");
}
dispatch_async(dispatch_get_main_queue(), ^{
[self hideAlertView]; // or however you want to do it
});
UIAlertView *alertAlmost = [[UIAlertView alloc] initWithTitle:#"Quase Pronto" message:#"Os seguintes contatos não tem código de área. Porfavor, selecione os contatos que você deseja adicionar o digito 9 e pressione Ok (caso não queira adicionar em nenhum, pressione Ok) " delegate:self cancelButtonTitle:#"Ok!" otherButtonTitles:nil];
[alertAlmost show];
[self presentViewController: secondViewController animated:YES completion: NULL];
});
}
I want the alert to dismiss, and then i can call the table view. Any sugestions?
Showing a UIAlertView is done asynchronously, so if you call showAlertView: at the top of the method, it'll show the alert view and then return immediately after, then do the rest of your method.
If you want the rest of your method to happen after the alert view is dismissed, you need to add yourself as the alert view's delegate, then implement the method
- (void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex
and do the rest of your stuff in there.
Edit: Okay, I think I get your problem. You're doing some time consuming synchronous operation on the main queue and that's blocking it so that the alert view isn't displayed until later.
You should move the time consuming operation to a different queue like so:
-(IBAction)getContacts:(id)sender {
// display the alert view
[self showAlertView:self];
// do the synchronous operation on a different queue
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );
// once this operation has finished, you can hide the alert view like so:
dispatch_async(dispatch_get_main_queue(), ^{
[self hideAlertView]; // or however you want to do it
});
});
}
You need to do the rest of the code in your "getContacts:" when your alert is dismissed. Set a delegate on your UIAlertView of "self" (the view controller showing the alert) and then do the "addressBook" stuff when the user clicks the button to dismiss the alert.
For example, implement the UIAlertViewDelegate method alertView:clickedButtonAtIndex: and do your address book stuff in there (I linked the documentation for you).
I think you're saying that you want to popup an alert, like a progress indicator, and while that alert is up, you want to start your other process. Currently, you request to have the alert shown immediately, but as the other answers have said, that call is asynchronous, and the UI thread does not manage to get the alert displayed before starting on the other work.
You could try this:
-(IBAction)getContacts:(id)sender {
[self showAlertView:(id)self];
[self performSelectorInBackground: #selector(initAddressBook) withObject: nil];
}
-(void)initAddressBook {
ABAddressBookRef addressBook = ABAddressBookCreate( );
CFArrayRef allPeople = ABAddressBookCopyArrayOfAllPeople( addressBook );
CFIndex nPeople = ABAddressBookGetPersonCount( addressBook );
}
If there's some problem with running the address book work in the background, you might even be able to give the UI thread enough time to get the alert posted with something like this:
-(IBAction)getContacts:(id)sender {
[self showAlertView:(id)self];
[self performSelector: #selector(initAddressBook) withObject: nil afterDelay: 0.1f];
}

multiple thread app crash, log said Unable to restore previously selected frame

interface file:
// ...
UITextView *statusTextView_;
UITableView *accountListTableView_;
NSMutableArray *accountList_;
NSString *lastStatus_;
// ...
#property (retain) UITextView *statusTextView;
#property (retain) UITableView *accountListTableView;
#property (retain) NSMutableArray *accountList;
#property (retain) NSString *lastStatus;
// ...
implement file:
// ...
#synthesize statusTextView=statusTextView_;
#synthesize accountListTableView=accountListTableView_;
#synthesize accountList=accountList_;
#synthesize lastStatus=lastStatus_;
- (void)aBtnTapAction:(id)sender
{
[self.lastStatus release];
NSString *buf = [[NSString alloc] initWithString:self.statusTextView.text];
self.lastStatus = buf;
[buf release];
for (NSDictionary *dict in self.accountList) {
if (TRUE == [[dict objectForKey:#"checked"] boolValue]) {
NSString *selectorName = [[NSString alloc] initWithFormat:#"%#:", [dict objectForKey:#"name"]];
SEL sel = NSSelectorFromString(selectorName);
[selectorName release];
if (YES == [self respondsToSelector:sel]) {
[self performSelectorInBackground:sel withObject:dict];
}
}
}
}
selectorName is one of followings
- (void)sina:(NSDictionary *)info
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
SinaController *sina = [[FooController alloc]
initWithUsername:[info objectForKey:#"username"]
andPasswd:[info objectForKey:#"passwd"]];
code = [sina post:self.lastStatus];
[sina release];
[pool release];
}
- (void)qq:(NSDictionary *)info
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
QQController *qq = [[FooController alloc]
initWithUsername:[info objectForKey:#"username"]
andPasswd:[info objectForKey:#"passwd"]];
code = [qq post:self.lastStatus];
[qq release];
[pool release];
}
app always crash in qq or sina thread, log said:
warning: check_safe_call: could not restore current frame
warning: Unable to restore previously selected frame.
Testing environment: MacOS10.6.7, XCode4 & Simulator.
I can't find any useful information by XCode Product -> analyze or Profile -> memory leaks.
I'm following Memory Management Programming Guide and try my best to fix it, but it still crash.
What's wrong with my code, why it crash ?
What are best practices that Objective-C coder when writing multiple thread pragram ?
Thanks for reply.
By releasing using the dot notation, you are over-releasing.
[self.lastStatus release];
should just be
self.lastStatus = nil;
Otherwise you are calling a release on lastStatus and then when you assign the new value using
self.lastStatus = buf;
Then this is first calling a release on the already released object. For more information read up about properties, the dot notation and memory management.

NSMutableString append data error

I have AsyncSocket like this.
- (void)onSocket:(AsyncSocket *)sock didReadData:(NSData *)data withTag:(long)tag {
NSString *message = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
[data getBytes:&tdata];
if (tdata > 5) {
if(bheader){
if(!charS){
if([message isEqualToString:#"S"]){
CMSG = message;
charS=YES;
}
}
else{
NSMutableString *tmp = [[NSMutableString alloc] initWithString:#""];
[tmp appendString:CMSG]; <<<<< This is code error at loop 2,
[tmp appendString:message]; the first loop success but second is fail
CMSG = tmp;
[tmp release];
}
}
else{
if (message){
cmessage = [[NSString alloc]initWithFormat:#"%#%#",cmessage,message] ;
}
else
NSLog(#"Error converting received data into UTF-8 String");
cdata++;
if(cdata==idata) {
msgComplete=YES;
}
}
if (msgComplete) {
NSDictionary *userInfo = [NSDictionary dictionaryWithObject:cmessage forKey:kNotificationMessage];
[notificationCenter postNotificationName:kNotification object:self userInfo:userInfo];
cmessage=#"";
CMSG=#"";
msgComplete=NO;
bheader=YES;
cdata=0;
charS=NO;
[cmessage release];
}
}
[sock readDataToLength:1 withTimeout:-1 tag:0];
}
This code fail at second loop at [tmp appendString:CMSG]; Thread 1: Program received signal "SIGABRT"
How fix this error ?
Thanks gurus,
CMSG is assigned to tmp but tmp is released right afterwards. CMSG needs to be retained throughout the loop.
CMSG = tmp; //<< should be CMSG = [tmp retain];
[tmp release];
Now you have another potential problem. You are using a deprecated method here
[data getBytes:&tdata];
if (tdata > 5) {
getBytes: was deprecated because of a potential buffer overrun and the result of getBytes is not appropriate to use for if(tdata > 5). If you want to check the length of bytes get that that from the NSData object.
I see an error that may or may not be the ultimate problem here. In the final conditional statement, you have:
cmessage=#"";
...
[cmessage release];
I don't think you should be releasing that string. I don't actually know all of the ins and outs of NSString objects that are defined in that way (as opposed to stringWithFormat: or initWithString:), but I don't think that you have ownership of that string object. You shouldn't have to release it.
Remove that release message and see if it helps.

Problem pushing a viewcontroller

I have a problem with this code. I have been looking for the solution and get the following warning:
warning: (Messages without a matching method signature will be assumed to return 'id' and accept '...' as arguments.).
I know that there probably is a problem with the .h file but i cannot find where.
#import <UIKit/UIKit.h>
#class NewGameViewController;
#class AccessCurrentGameData;
#class QandA_ViewController;
enum {
kTagNewGame = 1,
kTagContinueGame = 2,
};
#interface MainViewController : UIViewController <UIAlertViewDelegate> {
IBOutlet NewGameViewController *newGameViewController;
IBOutlet QandA_ViewController *qanda_ViewController;
UIAlertView *continueExistingGame_alert;
UIAlertView *zeroGameFile_alert;
NSString *title_txt;
NSString *message_txt;
NSString *cancelButton_txt;
NSString *otherButton_txt;
UIAlertView *myAlert;
}
#property (nonatomic, retain) IBOutlet NewGameViewController *newGameViewController;
#property (nonatomic, retain) IBOutlet QandA_ViewController *qanda_ViewController;
#property (nonatomic, retain) UIAlertView *myAlert;
-(IBAction)continueGame_button:(id)sender;
-(IBAction)newGame_button:(id)sender;
#end
The .m file:
-(IBAction)continueGame_button:(id)sender {
//=====CHECK IF THERE IS AN ON-GOING GAME, IF SO CONTINUE=====//
AccessCurrentGameData *isThereAnOngoingGameFunction = [AccessCurrentGameData new];
BOOL ongoingGame = [isThereAnOngoingGameFunction checkIfGameOngoing];
[isThereAnOngoingGameFunction release];
NSLog(#"+ + +continueGame_button+ + +");
NSLog(#"ongoingGame = %#\n", (ongoingGame ? #"YES" : #"NO"));
//
if (ongoingGame == YES) {
NSLog(#"+++++++++ ONGOING GAME +++++++++");
myAlert = [[UIAlertView alloc]
initWithTitle:#"Fortsätta spel"
message:#"Det finns ett aktivt spel, klicka Spela eller Tillbaka"
delegate:self
cancelButtonTitle:#"Tillbaka"
otherButtonTitles:#"Spela", nil];
myAlert.tag=kTagContinueGame;
[myAlert show];
[myAlert release];
}
}
// Load new game screen
-(IBAction)newGame_button:(id)sender {
myAlert = [[UIAlertView alloc]
initWithTitle:#"Varning"
message:#"Om du går vidare kommer pågående spel stoppas och nollställas!"
delegate:self
cancelButtonTitle:#"Tillbaka"
otherButtonTitles:#"Fortsätt", nil];
myAlert.tag=kTagNewGame;
[myAlert show];
[myAlert release];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
switch(myAlert.tag ) {
case kTagContinueGame:
NSLog(#"kTagContinueGame");
NSMutableArray *continueGameArray = [[NSMutableArray alloc] initWithCapacity:0];
AccessCurrentGameData *getCurrentGameInfo = [AccessCurrentGameData new];
continueGameArray = [getCurrentGameInfo continueTheCurrentGame];
[getCurrentGameInfo release];
NSLog(#"continueGameArray %#", continueGameArray);
[continueGameArray release];
QandA_ViewController * temp = [[QandA_ViewController alloc] init];
[self setQandA_ViewController:temp]; //>>>>>HERE IS THE PROBLEM
[temp release];
[[self navigationController] pushViewController:qanda_ViewController animated:YES];
break;
case kTagNewGame:
NSLog(#"kTagNewGame");
AccessCurrentGameData *zeroCurrentGameFileFunction = [AccessCurrentGameData new];
[zeroCurrentGameFileFunction firstCreationOrRestoreOfGameDataFile];
[zeroCurrentGameFileFunction release];
NewGameViewController * temp2 = [[NewGameViewController alloc] init];
[self setNewGameViewController:temp2];
[temp2 release];
[[self navigationController] pushViewController:newGameViewController animated:YES];
break;
default:
break;
}
}
I get the following output:
2011-02-12 22:20:40.943 FamQuiz_R0_1[6346:207] -[MainViewController setQandA_ViewController:]: unrecognized selector sent to instance 0xa120980
2011-02-12 22:20:40.945 FamQuiz_R0_1[6346:207] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[MainViewController setQandA_ViewController:]: unrecognized selector sent to instance 0xa120980'
There's a simple typo. You declared a property for QandA_ViewController *qanda_ViewController, so the setter's name will be setQanda_ViewController with a capital Q, but a lowercase a (only the first letter is capitalized).
Try [self setQanda_ViewController:temp]; or renaming your property.

Encoded nsstring becomes invalid, "normal" nsstring remains

I'm running into a problem with a string that contains encoded characters. Specifically, if the string has encoded characters it eventually becomes invalid while a "normal" string will not.
in the .h file:
#interface DirViewController : TTThumbsViewController
<UIActionSheetDelegate,UINavigationControllerDelegate,UIImagePickerControllerDelegate>
{
NSString *sourceFolder;
NSString *encodedSourceFolder;
}
#property (nonatomic, retain) NSString *sourceFolder;
#property (nonatomic, retain) NSString *encodedSourceFolder;
in the .m file:
- (id)initWithFolder:(NSString*)folder query:(NSDictionary*)query {
if (self = [super init]) {
sourceFolder = folder;
}
return self;
}
Up to now everything seems to run as expected. In viewDidLoad I have the following:
sourceFolderCopy = [self urlEncodeValue:(sourceFolder)];
//I also have this button, which I'll refer to later:
UIBarButtonItem *importButton = [[UIBarButtonItem alloc] initWithTitle:#"Import/Export" style:UIBarButtonItemStyleBordered
target:self
action:#selector(importFiles:)];
self.navigationItem.rightBarButtonItem = importButton;
Which uses the following method to encode the string (if it has characters I want encoded):
- (NSString *)urlEncodeValue:(NSString *)str {
NSString *result = (NSString *) CFURLCreateStringByAddingPercentEscapes (kCFAllocatorDefault, (CFStringRef)str, NULL, CFSTR(":/?#[]#!$&’()*+,;="), kCFStringEncodingUTF8);
return [result autorelease];
}
If I NSLog result, I get the expected values. If the string has characters like a white space, I get a string with encoding. If the string doesn't have any characters that need to be encoded, it just gives me the original string.
I have a button on the nav bar which begins an image import process by opening an action sheet. Once the method for the action sheet starts, my string is invalid - but only if it contains encoded characters. If it is just a "normal" string, everything is fine and acts as expected. Am I off on my encoding? At first I thought it might be a memory problem but I can't figure out why that would affect only encoded strings.
Here's where the action sheet is defined (and the first place I can see the encoded string becoming invalid) the NSLog statements are where it crashes:
- (IBAction)importFiles:(id)sender {
NSLog(#"logging encodedSF from import files:");
NSLog(#"%#",encodedSourceFolder);//crashes right here
NSLog(#"%#",sourceFolder);
if (shouldNavigate == NO)
{
NSString *msg = nil;
msg = #"It is not possible to import or export images while in image selection mode.";
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Unable to Import/Export"
message:msg
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
[alert release];
[msg release];
}
else{
UIActionSheet *actionSheet = [[UIActionSheet alloc]
initWithTitle:#"What would you like to do?"
delegate:self
cancelButtonTitle:#"Cancel"
destructiveButtonTitle:nil
otherButtonTitles:#"Import Photos (Picker)", #"Export Photos", nil, nil];
[actionSheet showInView:self.view];
[actionSheet release];
}
}
I don't get any crash errors going to the console. By using breakpoints I was able to see that the encodedSourceFolder is invalid in the action sheet method.
You should copy your passed in folder string in your initWithFolder:query: method like this or create a new string with:
- (id)initWithFolder:(NSString*)folder query:(NSDictionary*)query {
if (self = [super init]) {
sourceFolder = [folder copy];
}
return self;
}
Otherwise your string gets autoreleased elsewhere.
Do not use retain for NSString properties. Use copy:
#property (nonatomic, copy) NSString *sourceFolder;
There are several questions/answers here that explain this further, such as Chris Hanson's response at:
NSString property: copy or retain?