0

xCode iOS not registering:

currentCard = [myBook getCard:cardIndex];

Having some difficulty calling a get method (name), for a string, within an Object(addressCard) at a particular index(int index), within an NSMutableArray(book), within an object(addressBook).

Basically an iOS viewController has its own instance of an addressBook that holds addressCards within an NSMutableArray it instantiates. However in the viewLoad of the viewController, the AddressBook however doesn't get the card.

Is there some particular form for syntax in this particular case?

Fairly new to iOS, because its an app there are several files, but the main issue is directly related to addressBook.m's addCard and getCard Methods. Project is based on a lesson in learning Objective-C by Kochan if anyone is familiar with it (or can recommend a better source for learning iOS).

Method within AddressBook.m

//Add a method for getting the current card in view
-(AddressCard*) getCard: (int) index{
    AddressCard *cardC = [book objectAtIndex:index];
    return cardC;    
}


ViewController.m

#import "ViewController.h"


@interface ViewController ()

@end

@implementation ViewController
{
    BOOL isNew;
    int cardIndex;
    AddressBook *myBook;
    AddressCard *currentCard;
    BOOL cardChanged;
}


- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.


    //Initialize the Address Book
    NSString *presetName1 = @"Dave Strider";
    NSString *presetName2 = @"Rose Tyler";
    NSString *presetName3 = @"Sherlock Holmes";

    NSString *presetEmail1 = @"TurntechGodhead@skaia.net";
    NSString *presetEmail2 = @"DoctorsBetterHalf@tardis.Who";
    NSString *presetEmail3 = @"SHolmes@221Baker.st";


    AddressCard *card1 = [[AddressCard alloc]init];
    AddressCard *card2 = [[AddressCard alloc]init];
    AddressCard *card3 = [[AddressCard alloc]init];

    [card1 setName: presetName1 andEmail:presetEmail1];
    [card2 setName: presetName2 andEmail:presetEmail2];
    [card3 setName: presetName3 andEmail:presetEmail3];

    [myBook addCard:card1];
    [myBook addCard:card2];
    [myBook addCard:card3];



    //set the addybook index to zero
    cardIndex = 0;

    //set card to current card
    //***** ISSUE IS HERE *****
    currentCard = [myBook getCard:cardIndex];




    //set field values ***** currentCard gains no variables. 
    [_nameField setText:[currentCard name]];
    [_emailField setText:[currentCard email]];

    isNew = false;
    cardChanged = false;

  //*****  TESTING SYNTAX *****
  // This method however works perfectly, the card, and its string are accepted ****
  //   [_nameField setText:[card1 name]];

   // [_nameField setText:presetName1];
   // [_emailField setText:presetEmail1];
}


- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}





- (IBAction)btnNext_touch:(id)sender {
//check bools



//go to next card, check for last.
    int i = [myBook entries];
    if (i == cardIndex)
    {cardIndex = 0;}
    else {
        cardIndex++;
    }



//reset current bools
    isNew = false;
    cardChanged = false;


    //set card to current card
    currentCard = [myBook getCard:cardIndex];

    //set field values
    [_nameField setText:[currentCard name]];
    [_emailField setText:[currentCard email]];

}

- (IBAction)nameFieldChanged:(id)sender {
    cardChanged = true;

    //    if (isNew != true)
    //  {

    //    [_nameField setText:[];
    //}   else{

    //}
}

- (IBAction)emailFieldChanged:(id)sender {
    cardChanged = true;
}


@end

Here are the rest of the classes if they would serve additional aid in comprehending this nubby problem.

ViewController.h
//
//  ViewController.h
//  Lozano007-p4
//
//  Created by antonio a lozano ii on 2/19/13.
//  Copyright (c) 2013 antonio a lozano ii. All rights reserved.
//

#import <UIKit/UIKit.h>
#import "AddressBook.h"


@interface ViewController : UIViewController


@property (strong, nonatomic) IBOutlet UITextField *nameField;
@property (strong, nonatomic) IBOutlet UITextField *emailField;


@property (strong, nonatomic) IBOutlet UIButton *btnNext;


- (IBAction)btnNext_touch:(id)sender;

- (IBAction)nameFieldChanged:(id)sender;
- (IBAction)emailFieldChanged:(id)sender;


@end



AddressCard.h

//
//  AddressCard.h
//  Lozano007-p4
//
//  Created by antonio a lozano ii on 2/19/13.
//  Copyright (c) 2013 antonio a lozano ii. All rights reserved.
//

#import <Foundation/Foundation.h>
@interface AddressCard : NSObject <NSCopying, NSCoding>

@property (nonatomic, copy) NSString *name, *email;
-(void) setName: (NSString *) theName andEmail: (NSString *) theEmail;
-(void) assignName: (NSString *) theName andEmail: (NSString *) theEmail;
-(NSComparisonResult) compareNames: (id) element;
-(void) print;
@end


AddressCard.m
//
//  AddressCard.m
//  Lozano007-p4
//
//  Created by antonio a lozano ii on 2/19/13.
//  Copyright (c) 2013 antonio a lozano ii. All rights reserved.
//

#import "AddressCard.h"

@implementation AddressCard
@synthesize name, email;

-(void) setName: (NSString *) theName andEmail: (NSString *) theEmail
{
    self.name = theName;
    self.email = theEmail;
}

// Compare the two names from the specified address cards
-(NSComparisonResult) compareNames: (id) element
{
    return [name compare: [element name]];
}

-(void) print
{
    NSLog (@"====================================");
    NSLog (@"|                                  |");
    NSLog (@"| %-31s |", [name UTF8String]);
    NSLog (@"| %-31s |", [email UTF8String]);
    NSLog (@"|                                  |");
    NSLog (@"|                                  |");
    NSLog (@"|                                  |");
    NSLog (@"|       O                O         |");
    NSLog (@"====================================");
}

-(id) copyWithZone: (NSZone *) zone
{
id newCard = [[[self class] allocWithZone: zone]init];
              [newCard assignName: name andEmail: email];
              return newCard;
}

              -(void) assignName: (NSString *) theName andEmail: (NSString *) theEmail
{
                  name = theName;
                  email = theEmail;
}
              -(void) encodeWithCoder: (NSCoder *) encoder
{
                  [encoder encodeObject: name forKey: @"AddressCardName"];
                  [encoder encodeObject: email forKey: @"AddressCardEmail"];
}
              -(id) initWithCoder: (NSCoder *) decoder
{
    name = [decoder decodeObjectForKey: @"AddressCardName"];
    email = [decoder decodeObjectForKey: @"AddressCardEmail"];
    return self;
}


@end


AddressBook.h

//
//  AddressBook.h
//  Lozano007-p4
//
//  Created by antonio a lozano ii on 2/19/13.
//  Copyright (c) 2013 antonio a lozano ii. All rights reserved.
//

#import <Foundation/Foundation.h> 
#import "AddressCard.h"
@interface AddressBook: NSObject <NSCopying, NSCoding>

//{

 //Add a mutable array for the address cards
  //  NSMutableArray *cardArray;

//}


@property (nonatomic, copy) NSString *bookName;
@property (nonatomic, strong) NSMutableArray *book;
-(id) initWithName: (NSString *) name;
-(void) sort;
-(void) addCard: (AddressCard *) theCard;
-(void) sort2;
-(void) removeCard: (AddressCard *) theCard;
-(int) entries;
-(void) list;
-(AddressCard *) lookup: (NSString *) theName;

//Add a getMethod for the Current Display'd card.
-(AddressCard*) getCard: (int) index;
@end


AddressBook.m
//
//  AddressBook.m
//  Lozano007-p4
//
//  Created by antonio a lozano ii on 2/19/13.
//  Copyright (c) 2013 antonio a lozano ii. All rights reserved.
//

#import "AddressBook.h"

@implementation AddressBook

@synthesize book, bookName;

// set up the AddressBook's name and an empty book
-(id) initWithName: (NSString *) name
{
    self = [super init];

    if (self) {
        bookName = [NSString stringWithString: name];
        book = [NSMutableArray array];

    }

    return self;
}

-(id) init
{
    return [self initWithName: @"Unnamed Book"];
            }


// Write our own book setter to create a mutable copy
-(void) setBook: (NSArray *) theBook
{
 book = [theBook mutableCopy];
}


-(void) sort
{
[book sortUsingSelector: @selector(compareNames:)];
}




// Alternate sort using blocks
-(void) sort2
{
[book sortUsingComparator:
    ^(id obj1, id obj2) {
                    return [[obj1 name] compare: [obj2 name]];}];
}


-(void) addCard: (AddressCard *) theCard
{
    [book addObject: theCard];
}



-(void) removeCard: (AddressCard *) theCard
{
    [book removeObjectIdenticalTo: theCard];
}


-(int) entries
{
    return [book count];
}


-(void) list
{
    NSLog (@"======== Contents of: %@ =========", bookName);

    for ( AddressCard *theCard in book )
        NSLog (@"%-20s %-32s", [theCard.name UTF8String],
               [theCard.email UTF8String]);

    NSLog (@"==================================================");
}

// lookup address card by name — assumes an exact match



-(AddressCard *) lookup: (NSString *) theName
{
    for ( AddressCard *nextCard in book )
        if ( [[nextCard name] caseInsensitiveCompare: theName]
            == NSOrderedSame )
            return nextCard;

    return nil;
}


-(void) encodeWithCoder: (NSCoder *) encoder
{
    [encoder encodeObject:bookName forKey: @"AddressBookBookName"];
    [encoder encodeObject:book forKey: @"AddressBookBook"];
}



-(id) initWithCoder: (NSCoder *) decoder
{
    bookName = [decoder decodeObjectForKey: @"AddressBookBookName"];
    book = [decoder decodeObjectForKey: @"AddressBookBook"];

    return self;
}


// Method for NSCopying protocol



-(id) copyWithZone: (NSZone *) zone
    {
id newBook = [[[self class] allocWithZone: zone] init];

[newBook setBookName: bookName];

// The following will do a shallow copy of the address book
    [newBook setBook: book];

        return newBook;
    }


//Add a method for getting the current card in view
-(AddressCard*) getCard: (int) index{
    AddressCard *cardC = [book objectAtIndex:index];
    return cardC;

}
@end

-- Once again, there isn't specifically an error message generated with the code. It's more the fact that the code line specified at the top doesn't have any effect on the code.

user1815714
  • 13
  • 1
  • 4
  • What is the error you see? – Firoze Lafeer Feb 20 '13 at 11:13
  • Convention is to not prefix getters with "get". Instead naming a method `getCard:` name it `card:`. A method that start with get is expected to return a value by reference. Following the convention not only makes it easy for others to understand your code but is also a hint that the compiler and analyzer use. – zaph Feb 20 '13 at 11:15
  • I should probably specify, its not an error, it's simply that the syntax I'm using doesn't update currentCard in the -(void) viewDidLoad method of viewController.m – user1815714 Feb 20 '13 at 11:16
  • @Zaph regarding the getter.. you're right, its the only instance in the entire program where I made that error. I've been playing around with it for hours and my java habits unearthed themselves. xl – user1815714 Feb 20 '13 at 11:20

1 Answers1

0

Is that the entire source for ViewController? If so, I don't see where you created the address book instance.

In general, if you send a message to something and nothing happens, you should check to see that "something" isn't nil. In your java days, you would have seen an NPE. In this language, nothing happens. 'myBook' is probably nil here.

Something like this in viewDidLoad should do:

myBook = [[AddressBook alloc] initWithName:@"Some Name"];
Firoze Lafeer
  • 17,133
  • 4
  • 54
  • 48
  • I do believe i declared it in the implementation, but perhaps doing so doesn't allocate it a place in memory. I'm going to attempt this and overview alloc/init – user1815714 Feb 20 '13 at 12:40
  • The ivar declaration gives you space for the pointer to the address book. It doesn't actually allocate or initialize the address book that the pointer is meant to point to. – Firoze Lafeer Feb 20 '13 at 12:44
  • You're absolutely right. There is no allocation for myBook or currentCard. :O Thank you for *pointing* this out. – user1815714 Feb 21 '13 at 00:59