Displaying question: (null)


#1

Hi, I am new to IOS programming and learning to build the first example in Chapter 1 without success.

First question, I am using Xcode 3.2.6 for Snow Leopard. Should I assume that the codes in 3rd edition also works for prior versions of Xcode?

Second question, the build was successful without any error but the display question is always (null). I have checked the code several times against the code in the book and they seem consistent.

Here is the code for QuizViewController.h

#import <UIKit/UIKit.h>

@interface QuizViewController : UIViewController {
	
	int currentQuestionIndex;
	
	// The model objects
	NSMutableArray *questions;
	NSMutableArray *answers;
	
	// The view objects - don't worry about IBOutlet -
	// we'll talk about it shortly
	IBOutlet UILabel *questionField;
	IBOutlet UILabel *answerField;

}

- (IBAction)showQuestion:(id)sender;
- (IBAction)showAnswer:(id)sender;

@end

And this is the code for QuizViewController.m

#import "QuizViewController.h"

@implementation QuizViewController


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
	// Call the init method implemented by the superclass
	self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
	
	if (self) {
		// Create two arrays and make the pointers point to them
		questions = [[NSMutableArray alloc] init];
		answers = [[NSMutableArray alloc] init];
		
		// Add questions and answers to the arrays
		[questions addObject:@"What is 7 + 7?"];
		[answers addObject:@"14"];
		
		[questions addObject:@"What is the capital of Vermont?"];
		[answers addObject:@"Montpelier"];
		
		[questions addObject:@"From what is cognac made?"];
		[answers addObject:@"Grapes"];
	}
	
	// Return the address of the new object
	return self;
}

- (IBAction)showQuestion:(id)sender
{
	// Step to the next question
	currentQuestionIndex++;
	
	// Am I past the last question?
	if (currentQuestionIndex == [questions count]) {
		
		// Go back to the first question
		currentQuestionIndex = 0;
	}
	
	// Get the string at that index in the questions array
	NSString *question = [questions	objectAtIndex:currentQuestionIndex];
	
	// Log the string to the console
	NSLog(@"displaying question: %@", question);
	NSLog(@"currentQuestionIndex: %d", currentQuestionIndex);
	
	// Display the string in the question field
	[questionField setText];
	
	// Clear the answer field
	[answerField setText:@"???"];
}

- (IBAction)showAnswer:(id)sender
{
	// What is the answer to the current question?
	NSString *answer = [answers objectAtIndex:currentQuestionIndex];
	
	// Display it in the answer field
	[answerField setText:answer];
}

@end

I have even added an NSLog index printer to see where it is at. The index continues to count up and never resets.

The ShowAnswer button does not work and does nothing.

Any idea how to debug is appreciated. Thanks in advance!


#2

Put a debug log in the method:

- (IBAction)showAnswer:(id)sender
{
    // Debugging...
    NSLog ("%s", __PRETTY_FUNCTION__); // __PRETTY_FUNCTION__ is a predefined macro

   // What is the answer to the current question?
   NSString *answer = [answers objectAtIndex:currentQuestionIndex];
   
   // Display it in the answer field
   [answerField setText:answer];
}

Build and run to see if it is being activated when you tap the button. If it is not, check the connection from the button to the method.


#3

What does PRETTY FUNCTION do?

I’ve added the line and it does nothing, just crashes. The connections are checked and they seem correct.

Do the codes work in previous versions of Xcode? Any reason why it wouldn’t?


#4

It is a language-defined macro, (of value const char*), for method names.

For example:

int main (int argc, const char * argv[])
{
    @autoreleasepool { 
        NSLog (@"%s: %s", __PRETTY_FUNCTION__, "Creating a Foo...");
        Foo *foo = [[Foo alloc] init];
        [foo setupFoo];
    }
    return 0;
}

@implementation Foo

+ (void)initialize
{
    NSLog (@"%s", __PRETTY_FUNCTION__);
}

- (id)init
{
    NSLog (@"%s", __PRETTY_FUNCTION__);
    return [super init];
}

- (void)setupFoo
{
    NSLog (@"%s", __PRETTY_FUNCTION__);
}
@end

Check the output:

2012-06-27 18:06:05.622 Initialize[89965:503] int main(int, const char **): Creating a Foo...
2012-06-27 18:06:05.624 Initialize[89965:503] +[Foo initialize]
2012-06-27 18:06:05.624 Initialize[89965:503] -[Foo init]
2012-06-27 18:06:05.625 Initialize[89965:503] -[Foo setupFoo]

If it builds without any errors, your code should work even in the version of Xcode you are using; the code is not doing anything fancy.

Most likely cause: you are doing something not quite right when setting up connections in IB.

Can you build and run a simple foundation program, with no UI?


#5

OK, I have placed some debugging points and this particular section of the code never passes:

@implementation QuizViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{

	
	// Call the init method implemented by the superclass
	self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
	
	if (self) {
		
		NSLog (@"Testing Point");
		
		// Create two arrays and make the pointers point to them
		questions = [[NSMutableArray alloc] init];
		answers = [[NSMutableArray alloc] init];
		
		// Add questions and answers to the arrays
		[questions addObject:@"What is 7 + 7?"];
		[answers addObject:@"14"];
		
		[questions addObject:@"What is the capital of Vermont?"];
		[answers addObject:@"Montpelier"];
		
		[questions addObject:@"From what is cognac made?"];
		[answers addObject:@"Grapes"];
	}
	
	// Return the address of the new object
	return self;
}

The “Testing Point” checkpoint is never printed. I have only been to Chapter 3 of the book but I cannot get past this Chapter 1 example. Again, I am using Xcode 3.2.6. This initialization syntax does not seem to work for some reason.


#6
@implementation QuizViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
   // Call the init method implemented by the superclass
   self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
   
   if (self) {
      NSLog (@"Testing Point");
   ...
   }
....
    return self;
}

Are you actually invoking this method?

If not, add an init method which calls the designated initializer:

@implementation QuizViewController

- (id)init
{
    return [self initWithNibName:nil bundle:nil];
}

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
   // Call the init method implemented by the superclass
   self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
   
   if (self) {
      NSLog (@"Testing Point");
   ...
   }
....
    return self;
}
...

And then invoke it like this:

...
QuizViewController *quizViewController = [[QuizViewController alloc] init];
...

#7

Hi, thanks for the suggestion. I have added the code but it is still not working. The good news is that the “Testing Point” line is now printed on the console, which means init is invoked.

But the array content is still null. I added 3 print lines to see why the init process is not working properly.

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{

	
	// Call the init method implemented by the superclass
	self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
	
	if (self) {
		
		NSLog (@"Testing Point");
		
		// Create two arrays and make the pointers point to them
		questions = [[NSMutableArray alloc] init];
		answers = [[NSMutableArray alloc] init];
		
		// Add questions and answers to the arrays
		[questions addObject:@"What is 7 + 7?"];
		[answers addObject:@"14"];
		NSString *samsam0 = [questions	objectAtIndex:0];
		NSLog (@"%s",samsam0);
		
		[questions addObject:@"What is the capital of Vermont?"];
		[answers addObject:@"Montpelier"];
		NSString *samsam1 = [questions	objectAtIndex:1];
		NSLog (@"%s",samsam1);
		
		[questions addObject:@"From what is cognac made?"];
		[answers addObject:@"Grapes"];
		NSString *samsam2 = [questions	objectAtIndex:2];
		NSLog (@"%s",samsam2);

	}
	
	// Return the address of the new object
	return self;
}

The console shows this:

2012-06-29 23:08:24.987 Quiz[19461:207] Testing Point
2012-06-29 23:08:24.989 Quiz[19461:207] [„ 2012-06-29 23:08:24.990 Quiz[19461:207][„
2012-06-29 23:08:24.990 Quiz[19461:207] [„ 2012-06-29 23:08:24.991 Quiz[19461:207] displaying question: (null) 2012-06-29 23:08:24.992 Quiz[19461:207] currentQuestionIndex: 1 2012-06-29 23:08:30.655 Quiz[19461:207] Testing Point 2012-06-29 23:08:30.656 Quiz[19461:207][„
2012-06-29 23:08:30.657 Quiz[19461:207] [„ 2012-06-29 23:08:30.657 Quiz[19461:207][„
2012-06-29 23:08:30.659 Quiz[19461:207] displaying question: (null)
2012-06-29 23:08:30.661 Quiz[19461:207] currentQuestionIndex: 2
2012-06-29 23:08:35.707 Quiz[19461:207] Testing Point
2012-06-29 23:08:35.708 Quiz[19461:207] [„ 2012-06-29 23:08:35.709 Quiz[19461:207][„
2012-06-29 23:08:35.709 Quiz[19461:207] [„ 2012-06-29 23:08:35.710 Quiz[19461:207] displaying question: (null) 2012-06-29 23:08:35.711 Quiz[19461:207] currentQuestionIndex: 3 2012-06-29 23:08:36.910 Quiz[19461:207] Testing Point 2012-06-29 23:08:36.911 Quiz[19461:207][„
2012-06-29 23:08:36.912 Quiz[19461:207] [„ 2012-06-29 23:08:36.912 Quiz[19461:207][„
2012-06-29 23:08:36.914 Quiz[19461:207] displaying question: (null)
2012-06-29 23:08:36.914 Quiz[19461:207] currentQuestionIndex: 4

Question:

  1. The book does not describe any initialization invoking in Chapter 1 when building a sample IOS code. Is the included sample code supposed to work?

  2. I apologize for being a newbie. Why isn’t the array initialized?

Thanks in advance.


#8

Why dos the red log appear more than once? Something is not quite right. initWithNibName should be called only once.

If you can post your files (both *.h and *.m), it will be easier to diagnose the problem.


#9

I have ran into this same problem, I am also running Snow Leopard, this seems like it must be a problem with Snow Leopard. Any luck with this swindoro?


#10

Ok, here’s a newbie response. I’m running Snow Leopard too and ran into the same problem yesterday.
I noticed that the code in initWithNibName:bundle wasn’t executing for some reason.
After searching various forums I got the app to run correctly by adding an awakeFromNib or viewDidLoad method and placing the array initialization there

- (void)awakeFromNib { // or -(void)viewDidLoad {
	
	// Create two arrays and make the pointers point to them
	questions = [[NSMutableArray alloc] init];
	answers = [[NSMutableArray alloc] init];
	
	//Add questions and answers to the arrays
	[questions addObject:@"What is 7 + 7?"];
	[answers addObject:@"15"];
	
	[questions addObject:@"Question 2?"];
	[answers addObject:@"Answer 2"];
	
	[questions addObject:@"Question 3?"];
	[answers addObject:@"Answer 3"];
	
}

#11

Hi,

this is probably coming somewhat late, but nevertheless…

I had faced the same problem (Log outpout of “Displaying question: (null)”) and then also noticed that the initWithNibName function does not even get called.

After reading some other forum entries here I found out this was caused by having forgotten to disable the checkbox “Use storyboards” when creating the project.

I just deleted and recreated the project from scratch, but this time without using storyboards, and now it works fine, as described in the book.

And since it was pointed out in another forum entry (I think by Joe Conway) that it is preferable to do member variable initializations in the init* method, rather than in the viewDidLoad method (because the latter can be called more than once), I think I learned something important here.

Cheers,
Rudiger