Why my array instance is out of scope? - iphone

Could some one tell me why my array is out of scope?
Here's my class:
// Paper.h
#interface Paper : NSObject {
NSMutableArray* items;
}
#property (retain) NSMutableArray* items;
// Paper.m
#import "Paper.h"
#implementation Paper {
#synthesize items;
}
// ParserUtil.m
#implementation ParserUtil {
+(Paper*) parsePaper:(NSString*)file {
...
Paper* paper = [[[Paper alloc] init] autorelease];
// does the following line is the best practice?
paper.items = [[[MutableArray alloc] init] autorelease];
Item* item = ...; // create item instance
[paper.items addObject:item];
return paper;
}
// call the parser method
...
Paper* paper = [[ParserUtil parsePaper:#"SomeFile"] retain];
// when run to this line, the paper.items is out of scope
// seems all the items in the array are dispear
NSMutableArray* items = paper.items;
...
Could someone point out what is wrong here?
Many thanks!

It isn't.
An object cannot be out of scope, because objects do not have scope. What they can be is unreachable, which is what happens when you don't have any variables holding the object's pointer.
Variables can be out of scope. You can only use a variable within the same scope in which you declared it; you can't begin a compound statement, declare a variable, finish the compound statement, and use the variable, and you can't declare a variable in one function or method and then use it in a different one.
You said in your other question that it's the debugger telling you the variable is out of scope. This means one of two three things:
The variable really is out of scope. Move the variable or move the code that uses it, or just interrupt the debugger earlier (with a breakpoint, if necessary).
The debugger is just being stupid. This happens a lot. Try the po command or sprinkle your code with NSLog statements instead.
You're trying to examine a property-access expression. A property-access expression, by definition, must send an accessor message, which may have side effects; for that reason, the debugger won't do that just for you hovering over the expression, because that's too easy to do by accident. You must use the po command in the Debugger Console to send the accessor message and print the description of the result.

Related

where do I initialize NSMutable Dictionary?

I have an Array comprised of further sub-Arrays
I want to display a summary of the contents of the sub-arrays into a TableView with the count of occurrences of each entry. I have determined that the best and easiest way is through a NSMutableDictionary as an intermediate step.
I declare the dictionary in my implementation
#implementation ReviewViewController
{
NSMutableDictionary *dict;
}
and down in my methods I initialise and use it like so:
dict = [NSMutableDictionary new];
[dict setObject:[Observation entryCount] forKey:[observedItem species]];
The swapping of key and object is deliberate as its the count I want. I'm using the fact that values are retained, but keys are overwritten, so if i swap them round i get the curation for free.
It works!, but every time the method is invoked, the Dictionary is clobbered by the re-initalization so I only get the last thing entered. Anywhere else and it falls out of scope.
if I pass it as an arguement in the method name instead, I get the message "Local declaration of 'dict' hides instance variable ". The code is already an irreducable set of parts, so
so, where is the correct place for the instantiation?
I'd love to make my contribution here as a meaningful thanks, but before I can do that I'm going to look silly with such questions.
You would usually initialise it in your init method. For a view controller this is usually the following:
- (id)initWithNibName:(NSString*)nibName bundle:(NSBundle*)bundle {
if ((self = [super initWithNibName:nibName bundle:bundle])) {
dict = [NSMutableDictionary new];
}
return self;
}
I don't understand what you mean by "Anywhere else and it falls out of scope.". It's an instance variable. It is therefore in scope in any method in the class.
By the way, I would name your instance variables with an underscore prefix, e.g. _dict. This is common convention and it helps you to remember when using it that it's an instance variable.

iPhone block scope confusion about accessing object references

Most of the documented examples of block usage demonstrate closure with simple variables, but I've been confounded by any attempts to access objects which are present in the surrounding code. For example, this crashes in an ugly, unhelpful way:
#interface VisualizerPreset : EyeCandyPreset {
float changeSourceRate;
float (^frontPanelSlider2DisplayValueBlock)(void);
}
....
VisualizerPreset *it;
it = [[VisualizerPreset alloc] init];
it.changeSourceRate = 0.4;
it.frontPanelSlider2DisplayValueBlock = ^(void) {
return it.changeSourceRate;
};
....
// this crashes
NSLog(#"%f",it.frontPanelSlider2DisplayValueBlock());
One possible reason is that you've lost the block. A block is created in stack, not in the heap. So if you want to keep the block, you have to copy it; this will make a copy of the block in the heap.
float (^aVar) = [^{return 0.0;} copy];
Of course, you will have to also release it later.
Be careful who owns the copy of the block. Inside a block, all referenced objects are automatically retained. So it is easy to create a reference cycle. You can use __block modifier for this problem. Consider reading this http://thirdcog.eu/pwcblocks/

Difference between class property mVar and instance variable self.mVar

I am some what confused as to the difference between accessing an instance variable via self or just by name (when working inside the class).
For instance, take this class:
//In .h file:
#interface Register : NSObject {
NSString *mName;
}
- (id) initWithName:(NSString *) name;
//In .m file:
- (id) initWithName:(NSString *)name
{
if (self == [super init])
{
mName = name;
}
return self;
}
What's the difference between accessing the instance variable via
self.mName = name;
vs
mName = name;
Which isn't a #property and is not #sythenize'd.
Say it is this though, per this example:
//In .h file:
#interface Manange_My_ViewsViewController : UIViewController {
IBOutlet UILabel *countLabel;
}
#property (nonatomic, retain) IBOutlet UILabel *countLabel;
//In .m file:
#synthesize countLabel;
- (void) updateLabel:(NSUInteger)count
{
countLabel.text = [NSString stringWithFormat:#"%d", count];
}
But say I accessed countLabel as:
self.countLabel
What would be the difference?
Edit: Third example per users' answer:
Say it the iVar wasn't an IBOutlet:
//In .h file:
#interface Fake : NSObject {
NSString *mVar;
}
#property (nonatomic, retain) NSString *mVar;
//In .m file:
#synthesize mVar;
mVar = #"";
VS
self.mVar = #"";
Or is it the same - that in the first we are accessing the actual instance variable and in the second we're actually going through the auto created setter (via #synthesize)?
Thanks all!
Edit: Update in response to Peter Hosey ...
So your thinking the convention of mVarName is bad? I took that from my C++ days.
But what about the case when you do?
-(void) someMethod:(int) x
{
x = x;
}
You can't do that (Say 'x' is also a class variable)
But you can do:
-(void) someMethod:(int) x
{
mX = x;
}
But your saying its better to do:
-(void) someMethod:(int) x
{
self.x = x;
}
What's the difference between accessing the instance variable via
self.mName = name;
vs
mName = name;
The first is property access syntax. It translates to an accessor message to the object (in this case, self). That is, that statement implicitly translates to this message expression statement:
[self setMName:name];
(Awkward accessor names like that are why “mName” is a poor name for a property. There is property declaration syntax to work around that, letting you name the property “name” and your instance variable “mName” and map one to the other.)
The second example directly accesses the instance variable—no accessor message.
Which isn't a #property and is not #sythenize'd.
Say it is this though, …
If no property named “mName” is declared for a class, then you can't use property access syntax to access a property by that name on an instance of that class.
And it doesn't matter whether you synthesize the accessors, hand-wave them to a superclass with #dynamic, or define them yourself. That's how the object will respond to the accessor message, but the accessor message the compiler generates will be no different (since a property access could just as easily come from outside the class as from inside it).
Say it the iVar wasn't an IBOutlet:
That doesn't matter. IBOutlet only means anything to IB. Everything else doesn't care.
In fact, IBOutlet is currently just a macro that expands to nothing. After your code gets preprocessed, the word “IBOutlet” is no longer there, so the compiler never sees it. That's how little a difference it makes to anything but IB: None at all.
Edit in response to question edit
I said mName is bad as a property name, because of the accessor names that follow from it. The name of an instance variable is a separate issue, particularly since the property and ivar don't have to have the same name.
For a variable, be it an instance variable or a local variable, the choice of name or m_name or mName is purely a style choice.
someMethod: is generally the accessor, setX:. Within that method, self.x = x, which is [self setX:x], causes infinite recursion. So don't do that.
When someMethod: isn't the accessor (or init or dealloc), using the property is just fine and generally preferable. However, in that case, you're not likely to give one of its arguments the same name as an instance variable. When such a case could occur, name the local variable more specifically, because its purpose is more specific. This, too, is a style issue.
When it is the accessor, I name the local variable newX, having named the instance variable the same as the property, x. This is my own personal style; as I said, naming the property x, the ivar mX, and the local variable x is fine too (aside from the excessive brevity of this example).
OK, first off is the basic difference:
mVar = var;
This is just changing a value. That's it.
self.mVar = var;
This is equivalent to:
[self setMVar:var];
In other words, one invokes a method, the other does not. Using the #property syntax can give you some really neat benefits. For example, you get key-value coding compliance for free. That means that another object can observe this object's mVar property, and be automatically notified whenever it changes, without you doing anything. You don't get this if you just access the ivar directly. (Unless, of course, you implement it yourself. But why would you do that?)
You also get semi-free memory management. If you declare a property as (retain), then you don't have to [newValue retain] yourself. The synthesized method will do this for you (in both cases, you'd still have to [ivar release] in your dealloc method).
You also can get some degree of thread safety. If you don't declare a property as (nonatomic), then it is (by default) atomic (although that keyword does not exist; it's implied). That means that reading/updating the value of the property is an atomic operation. If you were to just access the ivar directly, you'd have to implement the atomicity yourself with a lock.
Basically, using the synthesized methods gets you some really neat stuff for free. The only reason I'd say to not use the #property syntax is if you have irrefutable evidence that invoking those methods is a bottleneck in your code. However, you'll be really hard pressed to come up with a situation where that would be the case.
First of all, with a read-only property--which an IBOutlet essentially is--it does not matter as much.
The key difference is that the property is actually calling the accessor method while the instance variable is being accessed directly.
Thus, for setting a retain property, using self and the accessor will release the old object and retain the new one. Setting the instance variable directly will NOT impact the retain counts of any objects.
Using #synthesize will generate standard accessors for you.
The key reason to use properties is that, since they are accessors, they can be read and/or modified from outside the class.

Initialize Objective-C string constants from plist

I have defined a constants class within my iphone program using the 'extern' and 'const' keywords as in the example described in:
Constants in Objective-C
At this point, I am trying to initialize some string constants from the contents of a plist file, instead of being defined right in the class, e.g., instead of having:
// Constants.m
NSString * const MyConstant = #"a constant";
I would like to have it initialized somewhere from the plist file. So far, I have done a test using the static +(void)load method, but I am not completely happy about it, e.g.:
// Constants.m
NSString * ALERT_QUIT_TITLE;
#implementation Constants
+ (void)load {
// this controller contains all the strings retrieved from the plist file
LabelsController *labels = [LabelsController instance];
ALERT_QUIT_TITLE = labels.alertQuitTitle;
}
#end
Using a log call I can verify that the load code gets called early in the app startup, even before the AppDelegate constructor. However, two things I see not good in this approach:
I have to remove the 'const' keyword, otherwise I get a compile error since I am trying to initialize a variable that is defined as constant
I get some sort of warning message about the autoreleased pool:
*** _NSAutoreleaseNoPool(): Object 0x50b330 of class NSPathStore2 autoreleased with no pool in place - just leaking
Stack: (0x905caf0f 0x904d8647 0x904e039f (etc)
I guess I could use a direct call to the Labels controller to retrieve the label, but I would like more to treat it like a constant having all the maint. advantages it provides.
Which would be the correct (recommended) way to initialize a constant from an external source, like in this case a plist? Hope you can help, I have lost a good few hours trying to resolve this!
Thank you in advance.
If you initialize from a plist file, then you do not have a constant. And you should not define it as such.
I am guessing what you want is to be able to treat this value as if it was a constant? And that can be achieved using lazy initialization instead.
NSString* AlertQuitTitle()
{
static NSString* title = nil;
if (title == nil)
{
LabelsController* labels = [LabelsController instance];
title = labels.alertQuitTitle;
}
return title;
}
Is there a good reason as to why you do not use the NSLocalizedString() macro to fetch the alert quit title?
The warning
As the warning states, you are executing the +load method outside of an auto release pool. Meaning that all calls to autorelease just leak memory. You can fix your method like this:
+ (void)load
{
// this controller contains all the strings retrieved from the plist file
NSAutoreleasePool* pool = [NSAutoreleasePool new];
LabelsController *labels = [LabelsController instance];
ALERT_QUIT_TITLE = labels.alertQuitTitle;
[pool release];
}
I would suggest using the NSUserDefaults method instead for storing data.
Load is called far too early in the process for most purposes. Even initialize is fairly early. As you've noted, there is no autorelease pool setup, so any use of it (which is quite hard to avoid) will give you warnings and possible leaks.
A better way to do it is to forget the constant entirely, and write LabelController alertQuitTitle to lazily initialize its database and cache its answer. Something like this (untested, uncompiled).
+ (NSDictionary*) labelStrings;
{
static NSDictionary* strings = nil;
if ( !strings ) {
// Allocate and laod and keep ownership of the NSDictionary
}
return strings;
}
+ (NSString*) alertQuitTitle
{
static NSString* alertQuitTitle = nil;
if ( !alertQuitTitle ) {
alertQuitTitle = [[LabelController strings] objectForKey:#"alertQuitTitle"];
}
return alertQuitTitle;
}
If you really want, you can convert alertQuitTitle into a macro and use that to easily create dozens of methods.
In your other code, if you really want to, you can write a method that caches the answer as well, but thats fairly pointless, instead just use [LabelController alertQuitTitle].
You can, if you prefer, use a singleton, but there is not much point even creating a single instance of LabelController unless you have other things for it to do - any data it needs can be stored as static variables. A singleton would be more inline with typical Cocoa behaviour though. Either way, the same technique will work.
To directly answer your question, it looks like you're calling load before an NSAutoreleasePool has been set up. Every thread needs its own NSAutoreleasePool; your main thread's NSAutoreleasePool is set up in main.m, which you can see if you open up that source file.
I usually initialize my application's globals in my App Delegate's init method.
But this looks like unnecessary optimization, and it's creating problems as a result. You should consider using string resources for something like this. See NSBundle localizedStringForKey:value:table:, and NSLocalizedString()

Public scope in Objective-C?

I’m sure this is a simple one, but it’s been elusive so far, and I’m stumped ...
How do I declare an Ivar so that it’s accessible from ALL Classes in a project?
[Don’t know if it matters, but the ivar in question is (an instance of) my Model class, whose data needs to be accessible to various view controllers.]
Best as I can tell from "The Scope of Instance Variables” in The Objective-C 2.0 Programming Language
... this would be by using the “#public” directive.
So I’ve tried this in the #interface block where the ivar is declared:
#interface ...
...
#public
ModelClass *theModel;
#end
... But when I try to refer to “theModel” in a different class, the compiler doesn’t auto-complete, and when I type it in anyway, the compiler shows:
“Error: ‘theModel’ undeclared (first use in this function)”.
I assume this is a question of Scope, and that I haven’t made the ivar available appropriately, but how? Somehow I need to access this, or make its pointer available somehow.
Any ideas would be VERY much appreciated. Many thanks!
Perhaps you forgot to put the instance variable inside the braces of the class where all instance variable declarations go?
#interface Foo : NSObject {
// other instance variable declarations
#public
ModelClass *theModel;
}
// method and property declarations
#end
Also, can you show us the code of how you are trying to access the instance variable from elsewhere? The proper syntax should be:
myFooInstance->theModel
where myFooInstance is a value of type "Foo *"
I make properties available to all views managed by a Tab Bar via a singleton representing my data model. This is efficient and allows all Views access to the data (as well as any other application elements. Creating the singleton is straightforward (there are a ton of examples on S.O.). The you just request the instance and get the property values you need.
Here is a framework fro creating the Singleton. The key points are the static instance and the fact that you do the initialization as [[self alloc] init];. This will ensure the object gets cleaned up correctly. All the methods at the bottom of the class are standard from the SDK Docs to make sure release calls are ignored (because the object is shared globally).
Singleton Boilerplate (ApplicationSettings.m):
static ApplicationSettings *sharedApplicationSettings = nil;
+ (ApplicationSettings*) getSharedApplicationSettings
{
#synchronized(self) {
if (sharedApplicationSettings == nil) {
[[self alloc] init]; // assignment not done here
}
}
return sharedApplicationSettings;
}
+ (id)allocWithZone:(NSZone *)zone
{
#synchronized(self) {
if (sharedApplicationSettings == nil) {
sharedApplicationSettings = [super allocWithZone:zone];
return sharedApplicationSettings; // assignment and return on first allocation
}
}
return nil; //on subsequent allocation attempts return nil
}
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (id)retain
{
return self;
}
- (unsigned)retainCount
{
return UINT_MAX; //denotes an object that cannot be released
}
- (void)release
{
//do nothing
}
- (id)autorelease
{
return self;
}
You cannot access iVars from any other class.
You have to declare a getter/setter method to change or view a variable from another class - what you are really looking for are properties, that make it easier to define and access these getter/setter methods.
In your example above, you'd have the property defined just after the block that defines the local variable in the header file:
#property (nonatomic, retain) ModelClass *theModel;
In the implementation file you'd have the getter/setter created with the #synthesize statement just after the #implementation line:
#synthesize theModel;
Then if you have an instance of your class created, you access the class instance variable like so:
myInstance.theModel = [[[ModelClass alloc] init] autorelease];
The reason #public & #private are in there are to define visibility for subclasses (which, being extensions of that class type also get all the class local variables defined by a superclass), not for any random class.
The standard Objective-C way of doing it is to have a class method that returns the ivar
In your .h file:
+ (id)defaultModel;
and in your .m file:
static ModelClass * defaultModelInstance;
#implementation ModelClass
+ (id)defaultModel {
if (!defaultModelInstance) {
defaultModelInstance = [[ModelClass alloc] init];
}
return defaultModelInstance;
}
#end
although this will need tweaking if you need a specific ivar instead of just "a ivar that's always the same"
this type of design is used by many Cocoa classes i.e. [NSWorkspace sharedWorkspace]
Think a C global variable.
Adding:
extern ModelClass* theModel;
after the #end in the header will make the variable visible anywhere you include the header.
In the ModelClass.cpp file add:
ModelClass* theModel;
before the class implementation.
The variable will still have a value of nil until you allocate and initialize it though and you will be resposible for ensuring that it gets deallocated at the correct time.
THANK YOU ALL for the very helpful discussion on this topic! Clearly there are several ways to approach things here, so this is a very useful assortment of techniques.
Just to let y'all know that in researching this issue further, I ran across a couple of other very helpful pages, listed below. They include mention of the NSNotificationCenter, which I hadn't heard of before; as well as the idea of the "dependency injection" design pattern.
The idea is to keep "low coupling"(1) between the classes, making the code more modular & better for unit testing.
And while the 'notification' pattern sounds like a great idea, in this case it may be a bit overkill, considering that I only need ONE instance of the data model throughout the run of the app, and it doesn't change throughout.
Finally, even though the "#public" compiler directive is well-documented in Apple's Obj-C guide(2), I later found a fascinating edict in a different doc stating that it shouldn't be used! Quoted from Apple's own Cocoa Fundamentals(3):
"Give the proper scope to your instance variables. Never scope a variable as #public as this violates the principle of encapsulation. ..."
(Strange that they don't mention this in their 'Objective-C 2.0' guide where the directive is actually explained.)
Anyway, here are a couple of other links I found to be full of some great insights as well. FYI:
S.O.: "What’s the best way to
communicate between
viewcontrollers?"(4) <<
CocoaWithLove: "Five approaches to
listening, observing and notifying in
Cocoa"(5)
CocoaWithLove: "Singletons,
AppDelegates and top-level data"(6)
Hope these help. Anyway, thank you all again!
Best,
rond
P.S. Yikes! It won't let me post more than one inline hyperlink, so I'm listing them here instead. Obviously, they’re all prefixed by “http://” ... :O
(1): en.wikipedia.org/wiki/Coupling_(computer_science)
(2): developer.apple.com/DOCUMENTATION/Cocoa/Conceptual/ObjectiveC/Articles/ocDefiningClasses.html#//apple%5Fref/doc/uid/TP30001163-CH12-TPXREF127
(3): developer.apple.com/documentation/Cocoa/Conceptual/CocoaFundamentals/AddingBehaviortoaCocoaProgram/AddingBehaviorCocoa.html#//apple_ref/doc/uid/TP40002974-CH5-SW12
(4): stackoverflow.com/questions/569940/whats-the-best-way-to-communicate-between-viewcontrollers
(5): cocoawithlove.com/2008/06/five-approaches-to-listening-observing.html
(6): cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html