Welcome to the MacNN Forums.

If this is your first visit, be sure to check out the FAQ by clicking the link above. You may have to register before you can post: click the register link above to proceed. To start viewing messages, select the forum that you want to visit from the selection below.

You are here: MacNN Forums > Software - Troubleshooting and Discussion > Developer Center > can't statically type

can't statically type
Thread Tools
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Jul 11, 2001, 07:03 PM
 
Is there any particular reason that project builder won't let me statically type an object?

kman
     
Dedicated MacNNer
Join Date: Feb 2001
Status: Offline
Reply With Quote
Jul 11, 2001, 07:54 PM
 
Can you be more specific? What language are you using? What error do you get? A code snippet would help.
     
kman42  (op)
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Jul 11, 2001, 08:56 PM
 
Yes, I can be more specific. I'm writing in ObjC.

If I change the following static types to id then I don't get this error: statically allocated objects not allowed.

IBOutlet NSTextField distanceField;
IBOutlet NSTextField exitField;
IBOutlet NSTextField hikeField;

However, if I use id types then this error:
Jul 11 18:56:27 Hiker[1958] *** -[NSConstantString setName:]: selector not recognized

when executing this code:

-(void) extractFields: (Hike *) aRec
{
[aRec setName: [hikeField stringValue]];
...

I have imported the necessary headers with the declarations. The 'selector not recognized' error led me back to the setName declaration and so I thought I would statically type it, but then I get the 'static allocation not allowed' error.

Thanks,
kman
     
Mac Enthusiast
Join Date: Jul 2001
Status: Offline
Reply With Quote
Jul 12, 2001, 12:41 PM
 
Originally posted by kman42:
<STRONG>Yes, I can be more specific. I'm writing in ObjC.

If I change the following static types to id then I don't get this error: statically allocated objects not allowed.

IBOutlet NSTextField distanceField;
IBOutlet NSTextField exitField;
IBOutlet NSTextField hikeField;</STRONG>
Easy fix... those should be:

IBOutlet NSTextField *distanceField;

Note the asterisk.... it's an object - you have to use a pointer. Enjoy!
     
kman42  (op)
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Jul 12, 2001, 01:50 PM
 
Thanks! Obviously, I'm still a beginner but I should have caught that one.

Any idea about this:

Jul 12 11:45:10 Hiker[2099] *** -[NSConstantString setName:]: selector not recognized

I believe it is in response to the following bit of code found in Hike.m:

-(void) setName: (NSString *) str;
{
[name autorelease];
name=[str copy];
}

which is called from this bit of code found in HikerController.m:

-(void) extractFields: (Hike *) aRec
{
[aRec setName: [hikeField stringValue]];

[aRec setTrailhead: [trailheadField stringValue]];
[aRec setExit: [exitField stringValue]];
[aRec setDistance: [distanceField floatValue]];
[aRec setNotes: [notesField string]];
}

HikerController.m imports HikerController.h and Hike.h.

Hike.h looks like this:

#import &lt;Cocoa/Cocoa.h&gt;

@interface Hike : NSObject &lt;NSCoding&gt;
{
NSString *name;
NSString *trailhead;
NSString *exit;
float distance;
NSString *notes;

}
-(id) init;
-(void) dealloc;

- (void) encodeWithCoder: (NSCoder *) coder;
-(id) initWithCoder: (NSCoder *) coder;

-(NSString *) name;
-(void) setName: (NSString *) str;

-(NSString *) trailhead;
-(void) setTrailhead: (NSString *) str;

-(NSString *) exit;
-(void) setExit: (NSString *) str;

- (float) distance;
-(void) setDistance: (float) val;

-(NSString *) notes;
-(void) setNotes: (NSString *) str;

@end


Sorry about the long post, but I figured that someone with more experience than me could probably just pick out the problem. I've modeled the app on TravelAdvisor, but I have run into a few snags. Basically, whenever I click on an item in the TableView it duplicates it. I have traced this to the above error because the error prevents the RecordNeedsSaving flag from changing to NO. So hopefully if I can fix the 'selector not recognized' error then things will work properly.

thanks again,
kman
     
Mac Enthusiast
Join Date: Jul 2001
Status: Offline
Reply With Quote
Jul 12, 2001, 02:10 PM
 
Originally posted by kman42:
<STRONG>Thanks! Obviously, I'm still a beginner but I should have caught that one.

Any idea about this:

Jul 12 11:45:10 Hiker[2099] *** -[NSConstantString setName:]: selector not recognized

I believe it is in response to the following bit of code found in Hike.m:

-(void) setName: (NSString *) str;
{
[name autorelease];
name=[str copy];
}</STRONG>
Well, if this is a direct copy/paste job, your error is the semicolon at the end of the first line of code.

Should be: - (void)setName: (NSString *)str

<STRONG>Sorry about the long post, but I figured that someone with more experience than me could probably just pick out the problem.</STRONG>
I think I'm just as much of a beginner as you. I just built Travel Advisor last week. =)

[ 07-12-2001: Message edited by: Carl Norum ]
     
Fresh-Faced Recruit
Join Date: Jul 2001
Status: Offline
Reply With Quote
Jul 12, 2001, 04:19 PM
 
Well, if this is a direct copy/paste job, your error is the semicolon at the end of the first line of code.
egads, NO! It's entirely valid to have:

- (void) myMethod: (id) param;
{
// implementation
}


It's a convenience to make copying and pasting method declarations from the header to the implementation easier.

Besides, he's getting a run-time error, not a compile error.

Jul 12 11:45:10 Hiker[2099] *** -[NSConstantString setName:]: selector not recognized
Well, it seems to me like you're passing in an NSString* to the extractFields: (Hike*) method -- which is an entirely valid thing to do! The problem would seem to be somewhere other than your posted code. Check everywhere you call extractFields and make absolutely certain you're passing in a Hike* and not something else.
     
kman42  (op)
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Jul 12, 2001, 05:30 PM
 
I think we need a remedial coding forum...

Here's the whole implementation of the Controller:

#import "HikerController.h"
#import "Hike.h"
@implementation HikerController


-(int) numberOfRowsInTableView: (NSTableView *) theTableView {
return [hikeKeys count];
}

-(id) tableView: (NSTableView *) theTableView
objectValueForTableColumn: (NSTableColumn *) theColumn
row: (int) rowIndex
{
return [hikeKeys objectAtIndex:rowIndex];
}
- (void) awakeFromNib
{
[hikeTableView setDataSource:self];
[hikeTableView sizeLastColumnToFit];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textDidChange
name:NSControlTextDidChangeNotification object:nil];

[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(textDidChange
name:NSTextDidChangeNotification object:notesField];

}

-(void) textDidChangeNSNotification *) notification
{
recordNeedsSaving=YES;
}


-(NSApplicationTerminateReply)applicationShouldTerm inateid)sender
{
NSString *storePath=[NSHomeDirectory()
stringByAppendingPathComponent:@"Documents/HikerData.hik"];
[self addRecord:self];
if (hikeDict)
[NSArchiver archiveRootObject:hikeDict toFile:storePath];
return NSTerminateNow;
}

-(id) init
{
NSString *storePath=[NSHomeDirectory()
stringByAppendingPathComponent:@"Documents/HikerData.hik"];
[super init];

hikeDict=[NSUnarchiver unarchiveObjectWithFile:storePath];

if (!hikeDict) {
hikeDict=[[NSMutableDictionary alloc] init];
hikeKeys=[[NSMutableArray alloc] initWithCapacity:10];
} else {
hikeDict=[[NSMutableDictionary alloc]
initWithDictionary:hikeDict];
hikeKeys=[[NSMutableArray alloc]
initWithArray:[[hikeDict allKeys]
sortedArrayUsingSelector:
@selector (caseInsensitiveCompare]];
}

recordNeedsSaving=NO;
return self;
}
-(void) dealloc
{
[hikeDict release];
[hikeKeys release];
[super dealloc];
}

- (IBAction)addRecordid)sender
{
Hike *aHike;
NSString *hikeName=[hikeField stringValue];

if (recordNeedsSaving && ![hikeName isEqualToString:@""])
{
aHike=[hikeDict objectForKey:hikeName];
if (!aHike) {
aHike=[[[Hike alloc] init] autorelease];
[hikeKeys addObject:hikeName];

[hikeKeys sortUsingSelector:@selector(compare];
[hikeTableView reloadData];
[hikeTableView selectRow:
[hikeKeys indexOfObject:hikeName]
byExtendingSelection:NO];
}
[self extractFields:aHike];
recordNeedsSaving=NO;

[hikeField selectText:self];
}
}

- (IBAction)blankFieldsid)sender
{
[hikeField setStringValue:@""];
[trailheadField setStringValue:@""];
[exitField setStringValue:@""];
[notesField setString:@""];
[distanceField setFloatValue:0.0];

[hikeField selectText:self];
}

- (IBAction)deleteRecordid)sender
{
NSString *hikeName = [hikeField stringValue];
[hikeDict removeObjectForKey:hikeName];
[hikeKeys removeObject:hikeName];

[hikeTableView reloadData];
[self blankFields:self];

}

- (IBAction)difficultyButtonClickedid)sender
{
}

- (IBAction)handleTVClickid)sender
{
Hike *aRec;
NSString *hikeName;
int index = [sender selectedRow];

if (index==-1) return;
hikeName=[hikeKeys objectAtIndex:index];

if (recordNeedsSaving) {
[self addRecord:self];
index=[hikeKeys indexOfObject:hikeName];
[hikeTableView selectRow:index byExtendingSelection:NO];
}
aRec=[hikeDict objectForKey:hikeName];
[self populateFields:aRec];
}

-(void) extractFields: (Hike *) aRec
{
[aRec setName:[hikeField stringValue]];

[aRec setTrailhead: [trailheadField stringValue]];
[aRec setExit: [exitField stringValue]];
[aRec setDistance: [distanceField floatValue]];
[aRec setNotes: [notesField string]];

[aRec setDifficulty: [difficultyButton indexOfSelectedItem]];
}

-(void) populateFields: (Hike *) aRec
{
[hikeField setStringValue: [aRec name]];
[exitField setStringValue: [aRec exit]];
[trailheadField setStringValue: [aRec trailhead]];
[distanceField setFloatValue: [aRec distance]];
[notesField setString: [aRec notes]];
[difficultyButton setState:1 atColumn:[aRec difficulty]-1];
[hikeField selectText:self];
}
@end
     
kman42  (op)
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Jul 12, 2001, 05:32 PM
 
sorry, that was longer than anticipated and really annoying.
     
Fresh-Faced Recruit
Join Date: Jul 2001
Status: Offline
Reply With Quote
Jul 12, 2001, 06:08 PM
 
Well, given that you're pulling your Hike* objects out of an NSDictionary that was unarchived, I'd be suspicious of archiving functions. I have never experimented with NSUnarchiver, but I'd suggest taking a closer look at the NSCoder part of your Hike object to ensure you're actually encoding them correctly as objects and not strings (which might be the default implementation?).
     
kman42  (op)
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Jul 12, 2001, 06:34 PM
 
They appear to be archived and unarchived as objects:

-(void) encodeWithCoder NSCoder *) coder
{
[coder encodeObject:[self name]];
[coder encodeObject:[self trailhead]];
[coder encodeObject:[self exit]];
[coder encodeObject:[self notes]];
[coder encodeValueOfObjCType:"f" at:&distance];

}

-(id) initWithCoder NSCoder *) coder
{
[self setName:[coder decodeObject]];
[self setTrailhead:[coder decodeObject]];
[self setExit:[coder decodeObject]];
[self setNotes:[coder decodeObject]];
[coder decodeValueOfObjCType:"f" at:&distance];

return self;
}
     
Fresh-Faced Recruit
Join Date: Jul 2001
Status: Offline
Reply With Quote
Jul 12, 2001, 10:27 PM
 
I'd say it's time to break out the debugger

I don't see anything obviously wrong with the Coder functions, but then I've never used NSCoder before so my analysis is meaningless. Try sticking some breakpoints here and there to make sure things are being called as expected.
     
kman42  (op)
Professional Poster
Join Date: Sep 2000
Location: San Francisco
Status: Offline
Reply With Quote
Jul 12, 2001, 11:02 PM
 
I put some breaks in and ran it using the debugger many times. That is how I came up with the extractFields call as causing the problem (when it call setName).

The flow of the program is as follows:
1)addRecord calls extractFields
2)extractFields calls setName
3) I get the error and the recordNeedsSaving variable never gets set to NO in the addRecord method after it calls extractFields

kman
     
Addicted to MacNN
Join Date: Mar 2000
Location: London, UK
Status: Offline
Reply With Quote
Jul 22, 2001, 03:59 AM
 
It looks like you're passing an object which no longer exists as aRec, and the runtime engine gets confused. I haven't read through all your code, but this was what was happening when I used a convenience constructor ([NSMutableArray arrayWithArray:anArray] or similar), which returned an autoreleased object. I forgot to retain it, and sometime later in the execution, the autoreleasepool released it. This took me no end of headbanging to find out. Make sure all your retains and releases are balanced...
     
Dedicated MacNNer
Join Date: Apr 2001
Location: San Francisco, USA
Status: Offline
Reply With Quote
Jul 22, 2001, 12:41 PM
 
Should you be doing a <font face = "courier">self = [super init]</font> in your initWithCoder: method?
     
Dedicated MacNNer
Join Date: Jan 2001
Location: Virginia, US
Status: Offline
Reply With Quote
Jul 22, 2001, 10:54 PM
 
I don't see anything in this code that's obviously wrong...

Although, you are missing a -setObject:forKey: call in the -addRecord: method to put the new Hike object in the dictionary -- this means that no new records are ever put in the dictionary, so it will remain empty (or whatever it was when it was unarchived).

Also note that your textDidChange method will be called whenever any textfield or text object anywhere in the app is edited. It seems a bit unorthodox but maybe that's what you want...

The only thing I can figure is one of two things: 1) The dictionary was originally archived with a NSString object as a value instead of a Hike object, so that's what exists in the dictionary now. Try examining the dictionary in the debugger or with printf/NSLog statements to see what the objects are inside the unarchived dictionary. 2) Somewhere else in your app you have an extra -release or -autorelease on a Hike object, which frees it prematurely, and an NSString instance gets allocated in the same memory location (meaning existing pointers to the Hike object now point to an NSString). Either would explain it, but I'd look at the archived dictionary first.

BTW, no, [super init] is not needed. If you're inheriting from a class that conforms to NSCoding, [super initWithCoder:coder] and [super encodeWithCoder:coder] should be called, but since this class is conforming to &lt;NSCoding&gt; on its own, it already is the "top level" class for -initWithCoder: and so should not call super. NSObject does not implement that method btw. -init is normally a completely separate initializer from -initWithCoder (they serve separate purposes) so normally they don't call each other, but sometimes it's done as a convenience if there's other code in -init that you need called and don't want to duplicate. This can be very confusing if the class is meant to be subclassed though.

Also, you can use @encode(float) instead of the hardcoded "f" in the NSCoding methods if you like.
     
   
Thread Tools
Forum Links
Forum Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On
Top
Privacy Policy
All times are GMT -5. The time now is 11:12 PM.
All contents of these forums © 1995-2011 MacNN. All rights reserved.
Branding + Design: www.gesamtbild.com
vBulletin v.3.8.7 © 2000-2011, Jelsoft Enterprises Ltd., Content Relevant URLs by vBSEO 3.3.2