Ok, today, after a detour to fix up and enhance the Android project, we're back on track with the IOS project. There's still a *lot* to do. Let's fire up Xcode and see where we're at. Ok, right now it's doing something like when I click on a selection it's not really doing anything. Let's check my most recent blog to see exactly where I was at on this. Ok, back at this post:
http://gettingintomobile.blogspot.com/2011/09/getting-onto-same-view.html
"iOS - Getting onto the same view"
I was attempting to highlight a single row. I did manage to highlight *all* the rows with this:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
cell.backgroundColor = [UIColor redColor];
}
i.e., the "willDisplayCell:forRowAtIndexPath" method. However, even by setting an "answerMode = true" in the "tableView:didSelectRowAtIndexPath" method, and checking it like so:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
if (answerMode){
cell.backgroundColor = [UIColor redColor];
}}
However, it does't highlight anything. When I try to print it, it says it's "nil". But it's a member variable. Let's try setting to false in where? Both the viewDidLoad and the viewDidAppear methods, just in case.
Nope, still nil. And when I go back and come back into the question screen, it's crashing on the startQuestionController on an undefined selector.
I need to gather one more piece of evidence. What gets called first - the willDisplayCell:forRowAtIndexPath, or the tableView:didSelectRowAtIndexPath?
Let's log the answers for now, although i could try the debugger.
Ok, one problem is that I'm somehow not correctly handling the answerMode variable, as it's crashing when I try to print it *after* setting it. It's not a full fledged object, it's a primitive, I guess, but after I set it I get a bad access error when trying to print it. For now, maybe let's try something like an NSString.
Let's try this. In the header, i'll declare the backing variable as this:
BOOL answerMode;
And the property as this:
@property (nonatomic, assign) BOOL answerMode;
In the code I'll set it to this:
answerMode = NO;
Or, like this when I want it to be true:
answerMode = YES;
And check it like this:
if (answerMode){
The reason being that it's really an unsigned char, and YES and NO are 1 and 0 respectively (see this post if you're interested in the details: http://iphonedevelopertips.com/objective-c/of-bool-and-yes.html)
Ok, let's rev 'er up for another try:
Hmm...exactly the same problem. So much for that solution.
Ok, well, let's try an NSString. We'll start out with this from http://iphonedevelopertips.com/cocoa/compare-nsstrings-objects.html"
[NSString stringWithFormat:@"This %@ is much less %s.", @"example", "contrived"];
Later we can compare string using this type of code (from the same url) :
char *cStr = "Homebrew";
NSString *str3 = [NSString stringWithUTF8String:cStr];
NSString *str4 = @"Homebrew";
if ([str3 isEqualToString:str4])
NSLog (@"str3 equals str4");
else
NSLog (@"str3 does not equal str4");
Ah, great. This code is working:
NSLog(@ " >>>>>>>>>>> didSelectRowRowAtIndexPath, before: Answer Mode: %@", answerMode);
answerMode = [NSString stringWithFormat:@"YES"];
NSLog(@ " >>>>>>>>>>> didSelectRowRowAtIndexPath, after: Answer Mode: %@", answerMode);
Here's the output:
2011-09-09 16:01:43.830 JlptQuizApp[6869:207] >>>>>>>>>>> didSelectRowRowAtIndexPath, before: Answer Mode: NO
2011-09-09 16:01:43.832 JlptQuizApp[6869:207] >>>>>>>>>>> didSelectRowRowAtIndexPath, after: Answer Mode: YES
So now let's just compare:
if ([answerMode isEqualToString:@"YES"]){
cell.backgroundColor = [UIColor redColor];
}
It seems from the output that, unfortunately, it's the "willDisplayCell:forRowAtIndexPath" that's called before "didSelectRowRowAtIndexPath". That's a bummer, because that's the only place for sure which I know of which names that specific row selected.
Hmm...bit of a pickle. Well, let's go googling some more.
Well, I've tried a few things. It looks like comparing an index row is the trick, but I've run into another problem. That is, the "willDisplayCell:forRowAtIndexPath" is only being called once.
Ah, I see - that's not the method I should be using. This is the method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
}
Sugar; that isn't being called when I click select either. This is a tough nut to crack. What I really want to do is figure how to redisplay the UITableView. What I might do is either go back up or into the detail. Probably go back up. Another possibility is to subclass something, but I'm not sure I won't just run into the same problem. Of course - *something* is is highlighting the the line that gets clicked. I'm afraid my knowledge of objective C and XCode and the Interface builder is bit to limited to work out how to get in the middle of that.
Well, it looks like that's the way to go after a bit more research. That way, I don't have to jump in an out of the view. SO suggests subclassing UIViewControllerCell.
Ok, well, it's a start - I managed to change the color of the *selected* row. But, I also need to change the color of a non-selected row. Also, it's cont non-compatible type warnings and it changed the font to white, but I'll worry about that later. The next big challenge is figuring out how to highlight a non-selected row.
Ok, let's wrap things up for now. Here's the code:
- (MyUITableViewCell *)tableView:(UITableView *)tv
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(@ " >>>>>>>>>>> cellforRowAtIndexPath");
// get the table veiw cell. Alwasy use the dequeue method
MyUITableViewCell *cell =
[ tv dequeueReusableCellWithIdentifier:@"cell"];
if( nil == cell ) {
// this sets up a resusable table cell
cell = [ [[MyUITableViewCell alloc]
initWithFrame:CGRectZero reuseIdentifier:@"cell"] autorelease];
// support line break mode for multiline
cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;
// 0 means any number of lines - necessary for multiline
cell.textLabel.numberOfLines = 0;
// set it up with a consistent font with the height calculation (see below)
cell.textLabel.font = [UIFont fontWithName:@"Helvetica" size:30.0];
}
// set the answer
if (indexPath.row < answers.count ) {
NSString *answer = [answers objectAtIndex:indexPath.row];
cell.textLabel.text = answer;
}
return cell;
}
//
// MyUITableView.m
// JlptQuizApp
//
#import "MyUITableViewCell.h"
@implementation MyUITableViewCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
NSLog(@"MyUITableViewCell, initWithStyle:reuseIdentifier called");
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
// Initialization code
}
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
NSLog(@"MyUITableViewCell, setSelected:animated called");
// Configure the view for the selected state
UIView *bg = [[UIView alloc] initWithFrame:self.frame];
bg.backgroundColor = [UIColor colorWithRed:.916 green:.9648 blue:.9844 alpha:1.0];
bg.backgroundColor = [UIColor redColor];
self.selectedBackgroundView = bg;
[bg release];
}
- (void)dealloc
{
[super dealloc];
}
@end
Some more googling finally got us on the right track. On this iphone dev sdk, http://www.iphonedevsdk.com/forum/business-legal-app-store/60258-ios-developer-program.html, i found that the I could actually call the
tableView:didSelectRowAtIndexPath from within the controller, since I have the table view passed in to the method - and can call that same method. After this ah-ha moment, I coded the following:
- (void)tableView:(UITableView *)tv didSelectRowAtIndexPath:(NSIndexPath *)indexPath}
...stuff..
NSIndexPath *correctAnswerPath = [NSIndexPath indexPathForRow:3 inSection:0];
UITableViewCell *correctCell = [tv cellForRowAtIndexPath:correctAnswerPath];
correctCell.backgroundColor = [UIColor greenColor];
... more stuff ..
Check out the green highlight - different than the blue highlighted row.
No comments:
Post a Comment