dealloc undeclared

Discussion in 'Mac Programming' started by jamesapp, Apr 17, 2008.

  1. macrumors 6502a

    Joined:
    Mar 7, 2008
    #1
    james-collinss-macbook-pro:prog15 jamescollins$ gcc -framework Foundation AddressBook.m prog15.11.m -o prog15.11
    AddressBook.m: In function ‘-[AddressBook initWithName:]’:
    AddressBook.m:8: warning: conflicting types for ‘-(id)initWithName:(NSString *)name’
    AddressBook.h:11: warning: previous declaration of ‘-(AddressBook *)initWithName:(NSString *)name’
    AddressBook.m: In function ‘-[AddressBook list]’:
    AddressBook.m:34: warning: ‘cString’ is deprecated (declared at /System/Library/Frameworks/Foundation.framework/Headers/NSString.h:345)
    AddressBook.m:39: warning: ‘cString’ is deprecated (declared at /System/Library/Frameworks/Foundation.framework/Headers/NSString.h:345)
    AddressBook.m:40: warning: ‘cString’ is deprecated (declared at /System/Library/Frameworks/Foundation.framework/Headers/NSString.h:345)
    AddressBook.m:48: error: ‘dealloc’ undeclared (first use in this function)
    AddressBook.m:48: error: (Each undeclared identifier is reported only once
    AddressBook.m:48: error: for each function it appears in.)
    AddressBook.m:48: error: syntax error before ‘{’ token
    AddressBook.m: At top level:
    AddressBook.m:53: warning: incomplete implementation of class ‘AddressBook’
    AddressBook.m:53: warning: method definition for ‘-dealloc’ not found

    got these error messages when i tried to compile a program from a book on Objective-C.

    -i was told cString is no longer used, so i understand that warning message.
    the thing that i don't understand is AddressBook.m:48 error: 'dealloc' undeclared (first use in this function)...
    i have in my interface file
    Code:
    -(void) dealloc;
    
    i will include the interface file which i called AddressBook.h
    Code:
    #import <Foundation/NSArray.h>
    #import <stdio.h>
    #import "AddressCard.h"
    
    @interface AddressBook: NSObject
    {
      NSString       *bookName;
      NSMutableArray *book;
    }
    
    -(AddressBook *) initWithName: (NSString *) name;
    -(void) addCard: (AddressCard *) theCard;
    -(int) entries;
    -(void) list;
    -(void) dealloc;
    
    @end
    
    and my implementation file which i called AddressBook.m
    Code:
    #import "AddressBook.h"
    
    @implementation AddressBook;
    
    // set up the AddressBook's name and an empty book
    
    -(id) initWithName: (NSString *) name
    {
      self = [super init];
      if (self) {
        bookName = [[NSString alloc] initWithString: name];
        book = [[NSMutableArray alloc] init];
        }
        
      return self;
    }
    
    -(void) addCard: (AddressCard *) theCard
    {
      [book addObject: theCard];
    }
    
    -(int) entries
    {
      return [book count];
    }
    
    -(void) list
    {
      int     i, elements;
      AddressCard *theCard;
      
      printf ("\n======== Contents of: %s =========\n",
               [bookName cString]);
      elements = [book count];
      
      for ( i = 0; i < elements; ++i ) {
          theCard = [book objectAtIndex: i];
          printf ("%-20s %-32s\n", [[theCard name] cString],
                       [[theCard email] cString]);
      }
      
      printf("========================================\
              ============\n\n");
      
              
    -(void) dealloc
    {
      [bookName release];
      [book release];
      [super dealloc];
    }
    @end
    
    and my test file which i called prog15.11.m
    Code:
    #import "AddressBook.h"
    #import <Foundation/NSAutoreleasePool.h>
    
    int main (int argc, char *argv[])
    {
      NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
      
      NSString *aName = @"Julia Kochan";
      NSString *aEmail = @"jewls337@axlc.com";
      NSString *bName = @"Tony Iannino";
      NSString *bEmail = @"tony.iannino@techfitness.com";
      NSString *cName = @"Stephen Kochan";
      NSString *cEmail = @"steve@kochan-wood.com";
      NSString *dName = @"Jamie Baker";
      NSString *dEmail = @"jbaker@kochan-wood.com";
      
      AddressCard *card1 = [[AddressCard alloc] init];
      AddressCard *card2 = [[AddressCard alloc] init];
      AddressCard *card3 = [[AddressCard alloc] init];
      AddressCard *card4 = [[AddressCard alloc] init];
      
      AddressBook *myBook = [AddressBook alloc];
      
      // first set up four address cards
      
      [card1 setName: aName andEmail: aEmail];
      [card2 setName: bName andEmail: bEmail];
      [card3 setName: cName andEmail: cEmail];
      [card4 setName: dName andEmail: dEmail];
      
      // now initialize the address book
      
      myBook = [myBook initWithName: @"Linda's Address Book"];
      
      printf ("Entries in address book after creation: %i\n",
                  [myBook entries]);
                  
      // Add some cards to the address book
      
      [myBook addCard: card1];
      [myBook addCard: card2];
      [myBook addCard: card3];
      [myBook addCard: card4];
      
      printf ("Entries in address book after adding cards: %i\n\n",
                  [myBook entries]);
                  
      // list all the entries in the book now
      
      [myBook list];
      
      [card1 release];
      [card2 release];
      [card3 release];
      [card4 release];
      [myBook release];
      [pool release];
      return 0;
    }
    
    didn't i declare dealloc in my interface file?
    what is the syntax error before '{' token?
     
  2. macrumors 6502

    Joined:
    Mar 31, 2005
    Location:
    London, England
    #2
    You're only importing <Foundation/NSArray.h> in your header file. -(void)dealloc is declared <Foundation/NSObject.h>

    I'd suggest that you change the import statement to the following:
    #import <Foundation/Foundation.h>

    This will include all the headers for the Foundation framework, including both NSObject.h and NSArray.h.

    It isn't necessary to redeclare -(void)dealloc in your header file, as it's declared by the superclass, NSObject.

    By the way, you can use -UTF8String instead of -cString.
     
  3. macrumors 68020

    Krevnik

    Joined:
    Sep 8, 2003
    #3
    Another game of spot the bug. :)

    The bug is here, at the end of the list method:

    Code:
    -(void) list
    {
      int     i, elements;
      AddressCard *theCard;
      
      printf ("\n======== Contents of: %s =========\n",
               [bookName cString]);
      elements = [book count];
      
      for ( i = 0; i < elements; ++i ) {
          theCard = [book objectAtIndex: i];
          printf ("%-20s %-32s\n", [[theCard name] cString],
                       [[theCard email] cString]);
      }
      
      printf("========================================\
              ============\n\n");
      
              
    -(void) dealloc
    {
      [bookName release];
      [book release];
      [super dealloc];
    } 
    
    If you look closely, the list method isn't closed off. This leads to the series of compile errors you see. Fix that, and the dealloc undeclared error should go away too.
     
  4. thread starter macrumors 6502a

    Joined:
    Mar 7, 2008
    #4
    where should i close off list.
    i tried at the end of
    Code:
    AddressCard *theCard;
    
    got more error messages
    i closed off list with '}', is that what you meant
     
  5. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #5
    Yes, put the } right after your printf() function call and before the dealloc method.
     
  6. thread starter macrumors 6502a

    Joined:
    Mar 7, 2008
    #6
    tried to put '}' right after printf and before dealloc
    got following error messages when i tried to compile

    james-collinss-macbook-pro:prog15 jamescollins$ gcc -framework Foundation AddressBook.m prog15.11.m -o prog15.11
    AddressBook.m: In function ‘-[AddressBook initWithName:]’:
    AddressBook.m:8: warning: conflicting types for ‘-(id)initWithName:(NSString *)name’
    AddressBook.h:11: warning: previous declaration of ‘-(AddressBook *)initWithName:(NSString *)name’
    Undefined symbols:
    ".objc_class_name_AddressCard", referenced from:
    literal-pointer@__OBJC@__cls_refs@AddressCard in ccBDrI05.o
    ld: symbol(s) not found
    collect2: ld returned 1 exit status
     
  7. macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #7
    It actually compiled, so now you're on to other bugs!

    Here's the one causing the first warning:

    in the header, initWithName returns an AddressBook pointer, while in the .m file it returns an id:
    Header:
    Code:
    -(AddressBook *) initWithName: (NSString *) name;
    .m file:
    Code:
    -(id) initWithName: (NSString *) name
     
  8. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #8
    Looks like you're not compiling AddressCard into your code. Try compiling like this:

    Code:
    gcc -framework Foundation [b]AddressCard.m[/b] AddressBook.m prog15.11.m -o prog15.11
     
  9. macrumors G4

    Eraserhead

    Joined:
    Nov 3, 2005
    Location:
    UK
    #9
    You also should put if blocks around the stuff you're releasing i.e.

    Code:
    if(bookName!=nil){
    	[bookName release];
    }
    if(book!=nil){
    	[book release];
    }
    
     
  10. macrumors 68020

    Krevnik

    Joined:
    Sep 8, 2003
    #10
    I have been curious, how needed is that? In my experience, calling release on a nil object is usually safe(ish).
     
  11. macrumors 603

    Cromulent

    Joined:
    Oct 2, 2006
    Location:
    The Land of Hope and Glory
    #11
    You said it yourself. Safe(ish) is not safe :). Better be safe than sorry, I can imagine trying to debug a possible error relating from that to be rather stressful.
     
  12. macrumors 68020

    Krevnik

    Joined:
    Sep 8, 2003
    #12
    Well, the main reason I say safe-ish, is that I haven't seen a crash from calling release on a nil object... But yeah, defensive is usually better. :p
     
  13. macrumors 68040

    iSee

    Joined:
    Oct 25, 2004
    #13
  14. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #14
    On the other hand if you're dealing with CoreFoundation types, you must check for NULL before releasing those when using CFRelease().
     
  15. macrumors 68000

    GeeYouEye

    Joined:
    Dec 9, 2001
    Location:
    State of Denial
    #15
    Nope, releasing nil in dealloc isn't just safe-ish, it's desired. Apple does it throughout Cocoa that way. There's a huge discussion of this very topic on Apple's Cocoa-dev mailing list. Go right ahead and get rid of those if's.
     
  16. macrumors 65816

    Sbrocket

    Joined:
    Jun 3, 2007
    Location:
    /dev/null
    #16
  17. macrumors 68020

    Krevnik

    Joined:
    Sep 8, 2003
    #17
    Awesome, now I know all those [var release] lines in my older code weren't the result of some delusion. I was being productively lazy. :)
     
  18. thread starter macrumors 6502a

    Joined:
    Mar 7, 2008
    #18
    compiled with AddressCard.m and program compiled
    still confused about
    warning: conflicting types for ‘-(id)initWithName:(NSString *)name’
    AddressBook.h:11: warning: previous declaration of ‘-(AddressBook *)initWithName:(NSString *)name’
     
  19. Moderator emeritus

    kainjow

    Joined:
    Jun 15, 2000
    #19
    Reread iSee's post. You need to keep the method declaration and implementation the same. They are different.
     
  20. thread starter macrumors 6502a

    Joined:
    Mar 7, 2008

Share This Page