How do I get NSString values from an Mutable Object Array? - objective-c

So I'm at the point in my app where I need to replace the image of a sprite and I think I know how to do it, but I'm having trouble implementing it. Basically, I'm making a domino game and I need to be able to flip the domino over so you can see the numbers.
Starting with my domino.h file....
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#interface Domino : CCSprite {
int int_leading;
int int_trailing;
int int_suitrank;
int int_playerid;
NSString *str_tilename;
NSString *str_mirrortilename;
}
#property int int_leading,int_trailing, int_playerid,
#property(nonatomic, retain) NSString *str_tilename;
#property(nonatomic, retain) NSString *str_mirrortilename;
-(void) print;
-(void) setTileName: (NSString *) theTileName;
-(void) setMirrorName: (NSString *) theMirrorName;
-(NSString *) str_tilename;
-(NSString *) str_mirrortilename;
#end
and then my .m file...
#import "Domino.h"
#implementation Domino
#synthesize int_leading,int_trailing, str_tilename, str_mirrortilename, int_playerid;
-(void) print {
NSLog (#"%i/%i", int_leading, int_trailing);}
-(void) setTileName: (NSString *) theTileName;
{
str_tilename=[[NSString alloc] initWithString: theTileName];
}
-(void) setMirrorName: (NSString *) theMirrorName;
{
str_mirrortilename=[[NSString alloc] initWithString: theMirrorName];
}
-(NSString *) str_tilename
{
return str_tilename;
}
-(NSString *) str_mirrortilename
{
return str_mirrortilename;
}
#end
Finally, in my game layer...
Domino *d06 =[[Domino alloc] initWithSpriteFrameName:#"blank.png"];
TileName= #"0-6.png";
MirrorName= #"6-0.png";
[d06 setTileName: TileName];
[d06 setMirrorName: MirrorName];
d06.int_leading=0;
d06.int_trailing=6;
At this point, I add all the dominoes together into a large mutable array that tracks which ones are still available for players to pick. The problem I'm having is that I either haven't found how to pull out the "TileName" from the mutable array, or maybe I have found it, but not understood it.
If I'm in a For loop, I would think the code should be something like
NSString *temp1=[[[movableSprites objectAtIndex:i]valueForKey:#"str_tilename"]string];
But this just results in the program crashing. Can you point me in the right direction?

NSString *temp1=[(Domino *)[movableSprites objectAtIndex:i] str_tilename];
I think using this code will solve your stuff... Check for the syntax.. Hope this helps.. :)

Related

No visible #interface for 'XYZPerson' declares selector 'initWithfirst:middlename:lastname'

This is my first objective code. I tried and searched to my best abilities but I did not get a solution to my problem. This is my code;
#import <Foundation/Foundation.h>
#interface XYZPerson:NSObject
#property NSString *firstname;
#property NSString *lastname;
#property NSString *middlename;
-(void)saysomething;
-(instancetype) initWithfirst:(NSString *) firstname
middlename:(NSString *) middlename
lastname:(NSString *) lastname;
+(void) greeting;
#end
#import "Myproj.h"
#implementation XYZPerson
-(instancetype) initWithfirst:(NSString *) firstname
middlename:(NSString *) middlename
lastname:(NSString *) lastname
{
self=[super init];
if(self)
{
_firstname=firstname;
_middlename=middlename;
_lastname=lastname;
}
return self;
}
-(void) saysomething
{
NSLog(#"Hi there %# %# %#",_firstname,_middlename,self.lastname);
[XYZPerson greeting];
}
+(void) greeting
{
NSLog(#"Have a great evening \n");
}
#end
When I try to create an object and initialize the properties its giving me an error
No visible #interface for 'XYZPerson' declares selector 'initWithfirst:middlename:lastname'
What I don't understand is it keeps prompting me another init method that I used previously (as seen in the screen shot)
I am unable to figure out the mistake, can somebody please help.
Thanks in advance

Objective C fast enumeration trouble

I am trying to use fast enumeration to print all songs that are in a playlist, but it seems like I am doing it wrong. Could someone help me out?
I have defined a Song class like this :
#interface Song : NSObject
#property (nonatomic,strong) NSString *title;
#property (nonatomic,strong) NSString *artist;
#property (nonatomic,strong) NSString *album;
#property (nonatomic,strong) NSString *playtime;
-(void) displaySong;
#end
displaySong function looks like this :
-(void) displaySong {
NSLog(#"%# - %# [%#] - %#\n", artist, title, album, playtime);
}
and now, to the PlayList class :
#interface PlayList : NSObject{
NSString *name;
NSMutableArray *playlist;
}
-(void) addSongToPlaylist: (Song *) song;
-(void) displayPlaylist;
#end
#implementation PlayList
-(void) addSongToPlaylist: (Song *) nameOfSong{
[playlist addObject:nameOfSong];
}
-(void) displayPlaylist{
NSLog(#"Playlist called %#:\n", name);
for(id obj in playlist)
{
if([obj isKindOfClass:[Song class]])
[obj displaySong];
}
}
// I also tried the displayPlaylist method this way, but it wasn't working either
-(void) displayPlaylist{
NSLog(#"Playlist called %#:\n", name);
for(Song *song in playlist)
{
[song displaySong];
}
#end
Could somebody please explain to me why my code isn't working?
And what displayPlaylist method is better?
You are never creating playlist
in the Playlist class' init add a playlist = [[NSMutableArray alloc] init] ;
And consider using a property for playlist (man — the similar names are quite annoying!)
If you don't want to have a init, you also can do:
-(void) addSongToPlaylist: (Song *) nameOfSong{
if(!playlist)
playlist= [[NSMutableArray alloc] init];
[playlist addObject:nameOfSong];
}
to answer the second question: it depends
if you know, that there are only instances of Song in the array, the second version is better, as a bit faster
if you don't know, it is the first, as otherwise a object would receive a message, it can't handle -> crash
or you can do
for(id obj in playlist)
{
if([obj respondsToSelector:#selector(displaySong)])
[obj displaySong];
}
if you wants to be sure, that the message is understood, no matter what object it is.
You don't appear to be initializing your playlist array. You can do so lazily in your methods by checking for nil or by overriding the init method for your PlayList class.

Incomplete Implementation Example Help!

I am working on an example from a book that I got and it doesnt seem to be working I am getting the warning Incomplete implementation. When I run the program I get an error singal "EXC_BAD_ACCESS". The warning is in the .m file at the line return [NSString stringWithFormat:#"Name:... Does anyone know what I am doing wrong?
my .m file
#import "RadioStation.h"
#implementation RadioStation
+ (double)minAMFrequency {
return 520.0;
}
+ (double)maxAMFrequency {
return 1610.0;
}
+ (double)minFMFrequency {
return 88.3;
}
+ (double)maxFMFrequency {
return 107.9;
}
- (id)initWithName:(NSString *)newName atFrequency:(double)newFreq atBand:(char)newBand {
self = [super init];
if (self != nil) {
name = [newName retain];
frequency = newFreq;
band = newBand;
}
return self;
}
- (NSString *)description {
return [NSString stringWithFormat:#"Name: %#, Frequency: %.1f Band: %#", name, frequency, band];
}
- (void)dealloc {
[name release];
[super dealloc];
}
#end
My .h file
#import <Cocoa/Cocoa.h>
#interface RadioStation : NSObject {
NSString *name;
double frequency;
char band;
}
+ (double)minAMFrequency;
+ (double)maxAMFrequency;
+ (double)minFMFrequency;
+ (double)maxFMFrequency;
-(id)initWithName:(NSString*)name
atFrequency:(double)freq
atBand:(char)ban;
-(NSString *)name;
-(void)setName:(NSString *)newName;
-(double)frequency;
-(void)setFrequency:(double)newFrequency;
-(char)band;
-(void)setBand:(char)newBand;
#end
radiosimulation.m file:
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
// insert code here...
NSMutableDictionary* stations = [[NSMutableDictionary alloc] init];
RadioStation* newStation;
newStation = [[RadioStation alloc] initWithName:#"Star 94"
atFrequency:94.1
atBand:'F'];
[stations setObject:newStation forKey:#"WSTR"];
[newStation release];
NSLog(#"%#", [stations objectForKey:#"WSTR"]);
newStation = [[RadioStation alloc] initWithName:#"Rocky 99"
atFrequency:94.1
atBand:'F'];
[stations setObject:newStation forKey:#"WKFR"];
[newStation release];
NSLog(#"%#", [stations objectForKey:#"WKFR"]);
[stations release];
[pool drain];
return 0;
You are declaring the following property accessor/mutators (getter/setters) but are not implementing them in your .m file.
-(NSString *)name;
-(void)setName:(NSString *)newName;
-(double)frequency;
-(void)setFrequency:(double)newFrequency;
-(char)band;
-(void)setBand:(char)newBand;
You need to implement all 6 of these methods in the .m file if you want to remove the warning about incomplete implementation.
You are effectively saying in the .h file that this is what your object is going to do, then not doing it in the .m. It won't generate an error, as objective-c messaging means that the message will be handed up to NSObject to deal with, which will also not have any matching implementation, and the messages will just be silently ignored. I don't like the way that this is only shown as a warning - but there you go.
That said, I wouldn't create the properties like this (there are neater ways of doing this in objective-c using #property), I would remove those method declarations in the .h and replace them with:
#property (nonatomic, retain) NSString *name;
#property (nonatomic, assign) double frequency;
#property (nonatomic, assign) char band;
These property declarations go in the same place as method declarations.
and then add the following to the .m file:
#synthesize name;
#synthesize frequency;
#synthesize band;
This will avoid having to write all that boilerplate accessor/mutator code that you are currently missing. Again, these go in the same region of the code as method implementations. Effectively the compiler is going to create name and setName methods automatically.
This code is untested - but should point you in the right direction for tidying up the incomplete implementation. It may fix your access error too - but that may require more detailed look at a stack trace.
Another point I'm not sure the code as written even needs to use get/set methods or properties. You might try removing the method declarations from the .h and see if it works. It seems that all the accesses to name, frequency and band are all from within the object.

Memory leak for object in array

I've started cleaning up my app before publication - using "Instruments" Leak analyzer.
I found a leak I can't plug. So I built a simple project to illustrate the problem. Please see code below. I put a button on the view to test fire the procedure "test". It always generates a leak.
First the header and code for an object named "theObj"
#import <Foundation/Foundation.h>
#interface theObj : NSObject {
NSString* theWord;
}
#property (nonatomic,retain) NSString* theWord;
#end
#import "theObj.h"
#implementation theObj
#synthesize theWord;
-(id) initWithObjects: (NSString *) aWord;
{
if (self = [super init]){
self.theWord = aWord;
}
return self;
}
-(void) dealloc{
[theWord release];
[super dealloc];
}
#end
Now the view controller
#import <UIKit/UIKit.h>
#import "theObj.h"
#interface LeakAnObjectViewController : UIViewController {
NSMutableArray* arrObjects;
}
- (IBAction)test;
#end
#import "LeakAnObjectViewController.h"
#implementation LeakAnObjectViewController
- (IBAction)test {
if (arrObjects == nil)
arrObjects = [[NSMutableArray alloc] init];
NSString* aStr = #"first";
[arrObjects addObject:[[theObj alloc] initWithObjects:aStr]];
[arrObjects removeAllObjects];
}
You alloc the object, which means you own it. Then you give it to the array, which means the array owns it as well. Then the array removes it, so you are the only owner. But you don't have a reference to the object anymore, so you can't release it, so it's just leaked.
Someone really needs to learn the rules around memory management. Specifically as it pertains to ownership, etc.

Objective-C dot syntax or property value?

I keep reading that dot syntax is possible but I keep getting errors that the struct does not contain members I am referencing. Perhaps its not the dot syntax so I have included details of what I am doing in hopes of a solution:
// MobRec.h - used as the objects in the MobInfo array
#import <Foundation/Foundation.h>
#interface MobRec : NSObject {
#public NSString *mName;
#public int mSpeed;
}
#property (nonatomic, retain) NSString *mName;
#property (nonatomic) int mSpeed;
// MobDefs.h - array of MobRecords
#interface Mobdefs : NSObject {
#public NSMutableArray *mobInfo;
}
#property(assign) NSMutableArray *mobInfo; // is this the right property?
-(void) initMobTable;
#end
// MobDefs.m
#import "Mobdefs.h"
#import "Mobrec.h"
#implementation Mobdefs
#synthesize mobInfo;
-(void) initMobTable
{
// if I use traditional method I get may not respond
[mobInfo objectAtIndex:0 setmName: #"doug"];
// if I use dot syntax I get struct has no member named mName
mobInfo[1].MName = #"eric";
}
// main.h
MobDefs *mobdef;
// main.m
mobdef = [[Mobdefs alloc] init];
[mobdef initMobTable];
although both methods should work I get erros on both. What am I doing wrong? My best thoughts have been that I am using the wrong #property but I think I have tried all. I am performing alloc in main. Ideally I would like to for this use dot syntax and cant see why its not allowing it.
A couple of things: (edit: original point #1 removed due to error)
Although the dot syntax is supported, the array index syntax for NSArray is not. Thus, your call to mobInfo[1] will not be the same as [mobInfo objectAtIndex:1]; Instead, mobInfo will be treated as a simple C-style array, and that call would be almost guaranteed to result in a crash.
You should not define variables in your header file as you do in main.h. The line MobDefs *mobdef; belongs somewhere in main.m.
edit: Here is how it should look:
MobRec.h
#interface MobRec : NSObject {
NSString *mName;
int mSpeed;
}
#property (nonatomic, retain) NSString *mName;
#property (nonatomic) int mSpeed;
MobRec.m
#implementation MobRec
#synthesize mName;
#synthesize mSpeed;
#end
MobDefs.h
#interface MobDefs : NSObject {
NSMutableArray *mobInfo;
}
#property(assign) NSMutableArray *mobInfo;
-(void) initMobTable;
#end
MobDefs.m
#import "MobDefs.h"
#import "MobRec.h"
#implementation MobDefs
#synthesize mobInfo;
-(void) initMobTable
{
// option 1:
[(MobRec*)[mobInfo objectAtIndex:0] setMName:#"doug"];
// option 2:
(MobRec*)[mobInfo objectAtIndex:0].mName = #"eric";
// option 3:
MobRec *mobRec = [mobInfo objectAtIndex:0];
mobRec.mName = #"eric";
}
main.m
MobDef *mobdef = [[MobDefs alloc] init];
[mobdef initMobTable];
...
[mobdef release]; // don't forget!
You need to either cast the object returned by -objectAtIndex:, or use a method call on it:
[[mobInfo objectAtIndex: 0] setMName: #"doug"];
or
((Mobrec *) [mobInfo objectAtIndex: 0]).MName = #"doug";
[mobInfo objectAtIndex:0 setmName: #"doug"];
There is no objectAtIndex:setmName method, so you're going to have to explain what you think this is even supposed to do.
mobInfo[1].MName = #"eric";
Use objectAtIndex to look something up in an NSArray object.