Problem pushing a viewcontroller - iphone

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.

Related

how to call a method within a method in iphone

i am facing problem when i call method within method of another class like this i have method for button when someone click on button
//within ViewController.m button method
-(IBAction)login:(id)sender
{
DBHelper *objdb = [[DBHelper alloc] init];
[objdb loginnow:textname.text andpassword:textpassword.text];
}
and this button method calling this method in DBhelper.m file and it succesfully calling this method
-(void) loginnow:(NSString *) username andpassword:(NSString *) password
{
[self createEditableCopyOfDatabaseIfNeeded];
[self initializeDatabase];
const char *sql;
NSString *querySQL = [NSString stringWithFormat: #"SELECT username, password FROM CONTACT WHERE username='%#' AND password='%#'",username,password];
sql = [querySQL UTF8String];
if (sqlite3_prepare_v2(database, sql, -1, &init_statement, NULL) != SQLITE_OK) {
NSAssert1(0, #"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(database));
}
while (sqlite3_step(init_statement) == SQLITE_ROW)
{
NSLog(#"char sql = %s" ,sql);
dbusername = [NSString stringWithUTF8String:(char *)sqlite3_column_text(init_statement,0)];
dbpassword = [NSString stringWithUTF8String:(char *)sqlite3_column_text(init_statement,1)];
}
if ([dbusername isEqualToString:username] && [dbpassword isEqualToString:password])
{
//DBHelper.callingViewController = self;
[self.callingViewController addview];
}
else if (dbusername != username || dbpassword != password)
{
NSLog(#"dbusername is = %#" ,dbusername);
NSLog(#"dbpassword is = %#" ,dbpassword);
UIAlertView *alert = [[UIAlertView alloc]
initWithTitle:#"Login Failed"
message:#"Username Or Password is not Correct"
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:#"OK ", nil];
[alert show];
[alert release];
}
sqlite3_reset(init_statement);
[self closeDatabase];
}
and also in DBhelper.h i define property for this
#property (strong) ViewController * callingViewController;
and within if condidtion in lognow method if password and username is succesully match i am calling this mathod in Viewcontroller.com file but am fail to call that
//ViewController.m
-(void) addview
{
DBHelper *f = [[DBHelper alloc] init];
f.callingViewController = self;
newview.center = CGPointMake(1000, 1000);
}
Though it's not wise to hold the viewController in the DBhelper(it breaks MVC), you could call your ViewController's method as your code but remember to set to pass your ViewController to the DBhelper. Maybe like this:
//ViewController.m
-(IBAction)login:(id)sender
{
DBHelper *objdb = [[DBHelper alloc] init];
[objdb loginnow:textname.text andpassword:textpassword.text viewController:self];
}
//DBHelper.m
-(void) loginnow:(NSString *) username andpassword:(NSString *)password viewController:(ViewController *)vc
{ ...
if ([dbusername isEqualToString:username] && [dbpassword isEqualToString:password])
{
[vc addview];
}
...
}
But in fact you should use a delegate (or block or notification, but delegate is the most case) here. Like this:
In DBHelper.h, before #interface, add
#class DBHelper;
#protocol DBHelperDelegate <NSObject>
-(void) DBHelp:(DBHelper *)helper didFinishedLoginSuc:(BOOL)suc;
#end
and between the #interface and #end tag, add(suppose you are not using ARC)
#property (nonatomic, assign) id delegate;
in the DBHelper.m, in the #implementation, add(suppose you are not using auto synthesize)
#synthesize delegate = _delegate;
Now, you can change the [self.callingViewController addview]; to
if (self.delegate && [self.delegate responseToSelector:#selector(DBHelp:didFinishedLoginSuc:)]) {
[self.delegate DBHelp:self didFinishedLoginSuc:YES];
}
Now you get a delegate prepared for every view controller which obey the DBHelperDelegate.
In your ViewController.h, tell the compiler that it obey the DBHelperDelegate by add behind the class declare:
#interface ViewController:UIViewController<DBHelperDelegate>
and change the addView method name to
-(void) DBHelp:(DBHelper *)helper didFinishedLoginSuc:(BOOL)suc
At last, when you click the button, set self as the objdb's delegate
-(IBAction)login:(id)sender
{
DBHelper *objdb = [[DBHelper alloc] init];
objdb.delegate = self;
[objdb loginnow:textname.text andpassword:textpassword.text];
}
Now, when you login successfully, -(void) DBHelp:(DBHelper *)helper didFinishedLoginSuc:(BOOL)suc in ViewController.m will be called and you can deal with your view.
Remember to set the delegate to nil when your viewController gets dealloc, or you will expect an memory error. Be careful.

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.

return a static const []

So in my model I have the following code... I am successfully able to return each individual value. I want to know how am I able to return the entire speakerTable []... Maybe some advice. Thanks!
typedef struct {
NSUInteger speakerID;
NSString * speakerName;
NSString * speakerPosition;
NSString * speakerCompany;
} SpeakerEntry;
static const SpeakerEntry speakerTable [] =
{
{0, #"name", #"position", #"company"},
{1, #"name", #"position", #"company"},
{-1, nil, nil, nil}
};
This works correctly...
-(NSString *) stringSpeakerCompanyForId:(NSUInteger) identifier{
NSString * returnString = nil;
if ([self helpCount] > identifier) {
returnString = speakerTable[identifier].speakerCompany;
}
return returnString;
}
This does not work at all..
-(id) getSpeaker{
//if ([speakerTable[0].speakerName isKindOfClass:[NSString class]])
// NSLog(#"YES");
NSArray * myArray3 = [NSArray arrayWithArray:speakerTable];
return myArray3;
}
arrayWithArray expects an NSArray, not a C array.
The first one works because you are using it like a C array.
Alternatively - don't use a struct, use an object instead:
Create a class called Speaker.
In Speaker.h
#interface Speaker : NSObject {}
#property (nonatomic, assign) NSUinteger id;
#property (nonatomic, copy) NSString name;
#property (nonatomic, copy) NSString position;
#property (nonatomic, copy) NSString company;
- (void)initWithId:(NSUInteger)anId name:(NSString *)aName position:(NSString *)aPosition company:(NSString *)aCompany;
#end
in Speaker.m
#import "Speaker.h"
#implementation Speaker
#synthesize id, name, position, company;
- (void)initWithId:(NSUInteger)anId name:(NSString *)aName position:(NSString *)aPosition company:(NSString *)aCompany {
if (!([super init])) {
return nil;
}
id = anId;
NSString name = [[NSString alloc] initWithString:aName];
NSString position = [[NSString alloc] initWithString:aPosition];
NSString company = [[NSString alloc] initWithString:aCompany];
return self;
}
- (void)dealloc {
[name release];
[position release];
[company release];
[super dealloc];
}
#end
And now in your calling code you can create an immutable array of speakers with:
Speaker *speaker0 = [[Speaker alloc] initWithId:0 name:#"name0" position:#"position0" company:#"company0"];
Speaker *speaker1 = [[Speaker alloc] initWithId:1 name:#"name1" position:#"position1" company:#"company1"];
Speaker *speakerNull = [[Speaker alloc] initWithId:-1 name:nil position:nil company:nil];
NSArray *speakerArray [[NSArray arrayWithObjects: speaker0, speaker1, speakerNull] retain]
[speaker0 release];
[speaker1 release];
[speakerNull release];
note: this is typed straight in, so feel free to mention/correct typos or errors
The method arrayWithArray takes in an NSArray as an argument, not a C array.

iPhone crash log

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.

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?