I have an NSMutableArray which is storing a list of other arrays. And when i run the code.
NSLog(#"%#",[[appDelegate teamRoster]objectAtIndex:[indexPath.row]class])
It returns and tells me that i am looking at an Array,
however when i try to do the following
[selectedRowerView tempArray] = [[appDelegate teamRoster]objectAtIndex:[indexPath.row]];
The program errors out. Anyone have any ideas why this might be happening?
You have to understand that [selectedRowerView tempArray] is actually a command / message that is being sent. In C++ equivalent, you are calling selectedRowerView->tempArray() = .... Which doesn't make logical sense because you cannot make an assignment to a function.
What you're trying to do is set the tempArray. If you have the proper setters/getters set-up, you can just run: selectedRowerView.tempArray = ...;
Just make sure that tempArray has a #property and is #synthesize'd.
How about this?
selectedRowerView.tempArray = [[appDelegate teamRoster]objectAtIndex:[indexPath.row]];
…assuming that tempArray is a synthesized property à la
#property (nonatomic, readwrite, retain) NSArray *tempArray;
#synthesize tempArray;
Clarification:
selectedRowerView.tempArray = …;
gets internally processed to
[selectedRowerView setTempArray:…];
which is a setter method.
While
selectedRowerView.tempArray;
gets internally processed to
[selectedRowerView tempArray];
which is a getter method.
Subtle but important difference.
The meaning of foo.bar depends on the very context (enclosing expression) it is used in.
Related
How can I efficiently find the attributes of an NSEntity object in a set ?
I have implemented it this way, but it seems to be inefficient. Is there a faster, easier, more efficient method of finding the attributes of an NSEntity object in a set, than this approach?
soccerTeamViewController.players = [[NSMutableArray alloc] init];
for (GGPlayer *playa in chelsea.players) {
[soccerTeamViewController.players addObject:playa.name];
}
^here chelsea is a GGTeam, it has a set of GGPlayers as a property.
Models:
GGTeam:
#property (nonatomic, retain) NSMutableSet *players;
GGPlayer:
#property (nonatomic, retain) NSString *name;
From a first time iOS-er.
Do not optimize prematurely. You have no evidence as to whether what you are doing is inefficient or not. If there appears to be a slowdown, use Instruments and figure it out. But don't guess, and especially don't guess in advance.
What you're doing is perfectly standard.
There is a more elegant way, namely to use KVC, as described here:
iPhone - getting unique values from NSArray object
But I have no reason to think that is more efficient.
Header file:
NSString *righta;
#property(nonatomic, retain) NSString *righta;
(I don't usually make #property declarations for my variables but thought this might help the variable persist through the class, though it hasn't)
Implementation file:
#synthesize righta;
- (void) function1 {
righta = [NSString stringWithFormat:#"A"];
}
- (IBAction)function2:(id)sender {
NSLog(#"righta is still %#", righta);
}
On trying to access the value of the string in the second function, I receive an "EXC_BAD_ACCESS" and the app crashes.
Any help would be GREATLY appreciated.
Thanks!
stringWithFormat returns an autoreleased object. You must retain it. Note that you are accessing the ivar directy, not the property so the string is not getting retained. Use the property instead:
self.righta = [NSString stringWithFormat:#"A"];
Some programmers prefer to synthesize their properties with a different ivar name to avoid accessing the ivar directly by mistake.
#synthesize righta = righta_;
You must use
self.righta = [NSString stringWithFormat:#"A"];
To assign the variable otherwise the accessor is not used and the value is not retained.
Change function1 to:
self.righta = [NSString stringWithFormat:#"A"];
You were assigning directly to the righta ivar without retaining the string.
Hopefully I can make this clear, but I am new to Objective-C and to be honest not great with Arrays in the first place.
So, I have a Singleton class (called SingletonState) that I am using to pass variables around my app (please can we leave the whether I should use Singleton classes out of this - I will fix that later). In this class, I have an NSMutableArray (called arrayMyEvents). I have also created a class that I am going to store a list of events (called EventClass). When the user logs in, I call a web service and get back 3 strings. The 3rd string is a comma separated list of value. I parse the data and populate the custom class EventClass. I then add this class to the SingletonState.arrayMyEvents.
I have all of this working. I can go to another ViewController and access the "count" of items in arrayMyEvents.
PROBLEM: I now want to edit one of the ScheduledEventsClass"es" in my array. How do I get access to it and edit some of the properties and update the one in my SingletonState class?
Here is some of the code, that I've tried:
NSString *sWebServiceEvents = [[NSString alloc] initWithFormat:#"%#", [result objectAtIndex:2]];
if ( [ sWebServiceEvents isEqualToString:#"NULL" ] != true ) {
NSArray *arrayEvents = [sWebServiceEvents componentsSeparatedByString:#","];
// If the array has not been initialized they initialize it.
if (sharedState.arrayMyEvents == nil) {
sharedState.arrayMyEvents = [[NSMutableArray alloc ] init ];
}
for (NSString * sEvent in arrayEvents) {
// Set equal to the value of the array (the Event Number) at the same
// position as the row that we are being asked to return a cell/row for.
EventClass *eventClass = [[EventClass alloc] retain];
eventClass.sEvent = sEvent;
[ sharedState.arrayEvents addObject:eventClass ];
}
NSLog(#"LoginView - sharedState.arrayMyEvents Count: %d", [sharedState.arrayMyEvents count]);
}
Here is me trying to access it in another ViewController:
EventClass *eventClass =
[sharedState.arrayMyEvents objectAtIndex:row ];
NSLog(#"eventClass.sEventNumber: ", eventClass.sEventNumber);
eventClass.sLocation = #"Jason's Big Location";
You're going to have some memory leaks from the sEvent loop. [[EventClass alloc]retain] leaves you an uninitialized EventClass object with a reference count of 2. You'll need to change that to [[[EventClass alloc] init] autorelease] to keep it from leaking. The arrayEvents NSMutableArray will retain it during the addObject: call. (Shouldn't that be [sharedState.arrayMyEvents addObject: eventClass] in the loop?)
After that, all you have to do to edit the EventClass object in the second block of code is edit it. The eventClass variable is a pointer to an object in the array. Anything done to that object doesn't affect the pointer referencing it, it affects data referenced by it. The code you have in the second block should change the sLocation of the selected object as you intend.
You have a few more memory leaks in there, too. Use Cmd-Shift-A to build with the static analyzer and it'll tell you where.
Maybe the problem is that you put them in sharedState.arrayEvents but try to take them out of sharedState.arrayMyEvents. Different variables.
Also, lots of memory leaks.
Thanks John and St3fan, your answers and time are appreciated!!!
I think that I figured out my issue:
Basically, the class that I created (EventClass) had the properties setup like this:
#property (nonatomic, assign) NSString *sStudyNumber;
#property (nonatomic, assign) NSString *sTheater;
but, they should be (or at least I got it to work like this):
#property (nonatomic, retain) NSString *sStudyNumber;
#property (nonatomic, retain) NSString *sTheater;
Then, in my second view I was able to do this:
EventClass *eventClass = [sharedState.arrayMyEvents objectAtIndex:row ];
NSLog(#"MyEvents: %#", eventClass.sEventNumber);
eventClass.sLocation = #"Jason's Big Location";
I then checked it in another method of the view using this and it was still there:
EventClass *eventClass = [sharedState.arrayMyEvents objectAtIndex:row ];
NSLog(#"MyEvents: %#", eventClass.sEventNumber);
NSLog(#"MyEvents: %#", eventClass.sLocation);
I also, checked it in yet another view and the value was maintained in the SharedState.arrayMyEvents without issue. :)
In the end, I believe that I boiled down to the difference between "assign" and "retain".
Now, on to the memory leaks :(
Please, let me know if you see any other issues with this.
Thanks,
Jason
for a day now I stare at the following routine and can't get my grips around it. I have a class such as:
MyClass.h
...
#interface MyClass : NSObject {
NSNumber *myNumber1;
NSNumber *myNumber2;
}
#property (nonatomic, retain) NSNumber *myNumber1;
#property (nonatomic, retain) NSNumber *myNumber2;
#end
and the m-file
#import "MyClass.h"
#synthesize myNumber1, myNumber2;
#implementation MyClass
-(id) init {
self = [super init];
NSLog(#"Retain Counts myNumber1: %d, myNumber2: %d", [myNumber1 retainCount], [myNumber2 retainCount]);
myNumber1 = [NSNumber inbitWithint:10];
myNumber2 = [NSNumber inbitWithint:2];
NSLog(#"Retain Counts myNumber1: %d, myNumber2: %d", [myNumber1 retainCount], [myNumber2 retainCount]);
return self;
}
...
I use this class as a globals container and instantiate it from every other class in my app using a
MyClass *myGlobals = [[MyClass alloc] init];
===>>> the weirdo >>>
Running the routine I have the following facinating console output:
Retain Counts (before) - myNumber1: 0, myNumber2: 0
Retain Counts (after) - myNumber1: 1, myNumber2: 26
How can that be?
Do not call `retainCount`
The return value of retainCount can only be considered accurate if you are calling it on an instance of a class you wrote and you have never ever not even once passed said instance to any API provided by the system.
The absolute retain count is an implementation detail for which you might not have any control.
Assuming, for the moment, that your code was typed and, thus, the errors are not really in your original code...
NSNumber caches a subset of common values. That is, for some numeric values, there is a single instance of NSNumber that is returned for all requests to retrieve an NSNumber instance wrapping that number.
If this is your actual code, it shouldn't work at all, it should simply crash. If not, you should cut and paste your actual code.
However, a couple of things.
First, if you use an NSNumber as an ivar, like anything else, you must take ownership of it. If you plan to use a convenience constructor, you must either assign it using the property on self, or send it an explicit retain message.
Second, you typed something like initWithInt: here. If you are actually using that message, then you have never actually allocated the number in the first place. You must replace this with one of the following:
myNumber1 = [[NSNumber alloc] initWithInt:10]; // explicitly create the number
myNumber1 = [[NSNumber numberWithInt:10] retain]; // take ownership through retain
[self setMyNumber1:[NSNumber numberWithInt:10]]; // use the property accessors to deal with ownership and the convenience constructor to create the number
However you choose to do it, you must at some point take ownership of the object.
You should never even look at retainCount as it carries little significance anyway. The reason you see the count of 26 is that probably somewhere in the frameworks (or even in your own app) other instances of NSNumber exist that are created with the same int 2. An NSNumber is immutable, and so as an optimization NSNumber probably just gives you back an instance it has created earlier. As long as you don't look at retainCount it doesn't matter to you.
The statement is:
//Pass the copy onto the child controller
self.childController.theFoodFacilityCopy = [self.theFoodFacility copy];
My property is set to:
#property (nonatomic, retain) FoodFacility *theFoodFacilityCopy;
The reason I think I have a leak is because copy retains the value and then my dot syntax property also retains the value. Doubly retained.
What is the correct way of writing the above statement?
yes, you do have a leak there.
SomeClass *someObj = [self.theFoodFacility copy];
self.childController.theFoodFacilityCopy = someObj;
[someObj release];
This mirrors the recommended approach for initializing an object too:
SomeClass *someObj = [[SomeClass alloc] init];
self.someProperty = someObj;
[someObj release];
In both cases the first line returns an objects with a retain count of 1, and you treat it identically after that.
As mentioned by others, that is indeed a leak. If you expect to be using copies in this way, it’s likely your property should be declared copy instead and the synthesized accessor will do the work for you.
You are right. The cleanest way is something like
id temp = [self.theFoodFacitlity copy];
self.childController.theFoodFacilityCopy = temp;
[temp release]
You want to read the apple site on memory management a lot until these rules become second nature.
What is the advantage of doing this vs just setting the property to copy?
#property (nonatomic, copy) FoodFacility *theFoodFacilityCopy;