What is the easiest way to create a global object. I have tried declaring the object outside the method with no luck.
#implementation UV_TouchpadViewController;
NSMutableString *string = [NSMutableString stringWithFormat:#"text"];
Very close -- you can't initialize a non-local variable with a non-const expression, and a method call is inherently non-const, even if it looks like it should be. So basically, change it to
NSMutableString *string;
but if it's only going to be used inside the implementation file (eg. other classes would only get at it through UV_TouchpadViewController, not get/set it directly (this is also the recommended pattern)), then qualify it as static, like so
static NSMutableString *string;
If on the other hand you do want to be able to access it directly from outside UV_TouchpadViewController, leave off the static, but add
extern NSMutableString *string;
to your header file (outside the class #interface), and whomever includes the header will be able to access it. (Note that you could instead just put NSMutableString *string; in your header file, however this is quickly becomes unclear)
Also, if you are trying to do this for a singleton class, (I can't think of a good reason to have a global mutable string -- you know they're not thread safe right?) I recommend reading Apple's docs on singletons first, where they suggest you use ivars, not global variables, even for singletons. However, UV_TouchpadViewController should not even be a singleton (if it is in any way a view controller), it should just have a single instance, if that's all you want.
If on the other hand you just want all UV_TouchpadViewControllers to have access to this one variable, note that across almost all languages this is considered a bad design pattern (globals are bad), and that you should instead stick it in, say, your app delegate (which is guaranteed to have a single globally accessible instance), where it can be an ivar+accessors, and generally considered a setting and (with a little extra code) persisted.
EDIT:
If you want to have a singleton that maintains global state, which I still recommend against -- you should create a class, like for instance ApplicationState, which handles all of the application's global state as a model object in the traditional model-view-controller pattern. I wont go into detail here because that would be highly redundant of a google search.
In your Application Delegate, somewhere, add an ivar ApplicationState *state, and a corresponding #property (and #synthesize in the implementation file).
There are few easier ways to shoot yourself in the foot than by using global variables.
You should never expose a dumb object like a string which has no access control to every object in the app. Any random piece of code anywhere in the app can change the mutable string leading to chaos as the app grows larger.
Usually when people want a global variable what they actually need is either the user defaults or a data model.
The user defaults (NSUserDefaults) is the preference persistence system that saves application state and user's settings both between launches and as the app runs. You can park small bits of data, such as strings, in the defaults and access them easily from anywhere in the app.
A data model is dedicated object that holds the applications data and manages access to it such that only the data model has final control. This makes it easy to tell what has changed the data and how. The data model can be a simple custom class or something elaborate such as core date. You can park the data model in the app delegate or create it as a singleton as the other answered have explained.
I have been using the Apple API for years and I have never needed to use a real global variable. If you think you need one, you probably have misunderstood something about application design in the Apple API. You might want to post a question explaining what you're trying to do with a global variable and what the best strategy should be for doing it without the dangers of using a global variable.
Do you need it for each instance of the class? If so, you should make it an Instance variable. Put
NSMutableString *string;
In your header
And then you can set it in any method in your class.
If this isn't what you meant, update your question or comment.
You can achieve that by implementing getter and setters in the delegate class.
In delegate .h file
Include UIApplication delegate
#interface DevAppDelegate : NSObject <UIApplicationDelegate>
NSString * currentTitle;
- (void) setCurrentTitle:(NSString *) currentTitle;
- (NSString *) getCurrentTitle;
In Delegate implementation class .m
-(void) setCurrentLink:(NSString *) storydata{
currentLink = storydata;
}
-(NSString *) getCurrentLink{
if ( currentLink == nil ) {
currentLink = #"Display StoryLink";
}
return currentLink;
}
So the variable you to assess is set in the currentlink string by setters method and class where you want the string ,just use the getter method.
AppDelegate *del=(AppDelegate *)[[UIApplication sharedApplication]delegate];
TO set:
[del setCurrentLink];
TO Get:
NSString *value=[del getCurrentLink];
All the best
Add:
NSMutableString *globalString = nil;
to any .m file of any object. The nil initialization adds a little safety, since nil objects can be "safely" messaged without outright crashing the app.
Add:
extern NSMutableString *globalString;
to the headers of any other objects that needs to access this global.
Add:
if (globalString == nil) {
globalString = [ [ NSMutableString stringWithFormat:#"text"] retain ];
}
to the init of any class(es) that could be the very first to touch this global, or to some init that happens even earlier.
Globals are a less verbose form of singleton, but with no access restriction or tracking. Use with caution.
actually as per my r&d i got that by use of extern we have to create an instance but the final thing is to #define your variable and can access any where you want without any creating of instance and other thing just directly use variable by its name....
Related
Working on iPhone, after a lot of headache and memory problems I just realized from other examples that we do not need to necessarly create #properties for each instance variable we define in header file. And actually I found out ivars easy to just allocate and release it after I use anywhere in the class, for #properties I have to use autorealese or I have serious problems and becareful how I allocate..
For instance for objects below, #properties(retain/copy..) is not used in headers in many examples;
{
NSURLConnection *connection;
NSMutableData *xmlData;
NsMutableString *string
}
But for some strings or object types #properties is used, I know that when we set #property cocoa creates some setters getters which are handling the relasing and retaining of the objects. But seems like as for xmlData or connection instance variables we do not need that and they do their job like this.
Are there some reference guidelines I can keep in mind on deciding whether or not to create #property's or just use simple ivars?
My only problem when using properties is not becuase I am lazy to define it, but when I carefully allocate and init them in code, I have to use autorelase and dont feel like I have the control when to release reset and allocate it again, and it gives me one more thing to worry about while and when and how should I release, reset it. I find ivars I can alloc and release anytime once anywhere easily without worrying about anything..or I am missing other things here.
Tnx
There seem to still be some misconceptions flying around about properties.
that we do not need to necessarly create #properties for each instance variable we define in header file
Correct. You can use private instance variables directly in your implementation file. However, since synthesized properties come with free memory management, you might as well take advantage. My rule of thumb is to use the ivar directly until the first time I find myself writing:
[ivar release];
ivar = [newIvar retain];
As Sam says, there is already a potential bug there if iVar == newIVar. This is the point at which I switch from using ivars directly to creating a property. However, I put the declaration of the new property in a class extension in the implementation file. This means that the property is officially not part of the public interface (and will cause compiler warnings if used accidentally).
when we set #property cocoa creates some setters getters which are handling the relasing and retaining of the objects.
Actually, no. The #property just declares a property. In order to automatically generate the getter and setter, you need to #synthesize it. You could, alternatively write your own getters and setter which do not even have to reference a real ivar.
Technically, you should not use the property in the init or dealloc methods because a subclass might have overridden them or (in dealloc) you might set off a KVO notification.
From Sam's answer and comments
If you want a property regardless, you could use a private interface at the top of the implementation file
As I say above, private categories have sort of been obsoleted by class extensions (which is near enough the same thing but allows you to put the implementation of the methods in the main class implementation).
If you want the benefits of using dot notation shorthand
Some of us would argue that there are no benefits to dot notation. It's a gratuitous and needless pollution of the struct member syntax. However, dot notation has no relation to #property declarations. You can use dot notation for any accessors no matter how they were declared, provided they adhere to the pattern -foo and and -setFoo:
Create properties only for variables that need to be accessed from outside the class. Any class variables that are used internally need not have getters/setters defined.
Generally speaking an abundance of properties indicates high coupling and poor encapsulation. You should restrict what variables your class exposes in the interface.
EDITED to respond to comment:
Using properties over direct access may be preferred because it gives you easy memory management.. for example:
// interface
#property (retain) Object *someVar;
// implementation
self.someVar = otherVar;
is the same as
// implementation
if (_someVar != othervar)
{
[_someVar release]
_someVar = [otherVar retain];
}
However you should not needlessly expose vars in your interface because it opens the class up for people to use in the wrong way.
If you want a property regardless, you could use a private interface at the top of the implementation file
#interface TheClass(Private)
// private stuff
#end
First of all, let me say that Sam's answer is complete, IMO, and gives you clear guidelines (+1 from me).
My only problem when using properties is not becuase I am lazy to define it, but when I carefully allocate and init them in code, I have to use autorelase and dont feel like I have the control when to release reset and allocate it again, and it gives me one more thing to worry about while and when and how should I release, reset it. I find ivars I can alloc and release anytime once anywhere easily without worrying about anything..or I am missing other things here.
You should not worry about autorelease in the following idiom:
self.stringProperty = [[[NSString alloc] initWith...] autorelease];
because this is the way that things are meant to work;
EDIT: [the above statement has several parts:
the object is allocated and initialized (retain count is 1);
immediately, the allocated object is also autoreleased; this means that the object will be released automatically, (more or less) when the control flow gets back to the main loop;
in the very same statement, the allocated object is assigned to a retained property, self.stringProperty; this has the effect of (once again) incrementing the retain count;
So, it is true that autorelease adds some "ambiguity", because the object will be released at a time that you don't know precisely (but pretty soon anyway), but assigning to the retain property will increase the retain count so that you have full control over the lifetime of the object.]
If you don't like the autorelease you can always use a constructor method which gives you back an autoreleased object, when available:
self.stringProperty = [NSString stringWith...];
or assign directly to the ivar:
stringProperty = [[[NSString alloc] initWith...] autorelease];
because by accessing directly the ivar you are bypassing the setter and getter. Anyway, do the it only in this case (IMHO) to avoid ambiguities.
More in general, the autorelease glitch is the only drawback that using properties has over directly accessing the ivars. The rest are, IMO, only advantages that in many cases will save your life, and if not your life, a leak or a crash.
There is nothing you cannot do with directly accessing the ivars and taking care of when it is necessary to release before assigning, or not forgetting to set to nil after releasing, etc., but properties will do that easier for you, so my suggestion is simply use them and accept the autorelease shortcoming. It's only a matter of getting the basic "idioms" right.
It has long been custom to access ivars directly. That is, IMO, fine from inside the same class, although many properties are classes and then properties provide protection against retain/release issues.
IMO, it is, however, preferrable to encapsulate most ivars into properties, especially those that have retain/release semantics, but also those that need special handling, i.e. for which you write your own handlers, instead of using the synthesized ones. That way you can filter access to certain ivars, or even create properties that don't have any backing storage, and are just "aliases" to other properties, e.g. an Angle class that has a degrees property giving the angle in degrees, and a radians property denoting the same angle in radians (this is a simple conversion), or a property that must do a dictionary search to find its value, etc.
In Delphi, which was (AFAICT) one of the first languages with properties as language construct at all, it is customary to wrap ALL ivars in properties (but not all have to be public), and there are many such "unreal" (I am deliberately avoiding the term "virtual" here) properties, i.e. the ones that are only implemented in code, and not just getters and setters for an ivar.
Properties provide encapsulation, abstraction and a degree of protection against certain often made errors, and that is why they are to be preferred over direct access to ivars, IMO.
Addition
It doesn't make sense to declare and implement (either via #synthesize or with custom setters and getters) public properties for each ivar. Only expose publicly what others may need. Internal state can also be exposed to your own code via properties, but that should be done with a private or empty category in the implementation file. That way you get the automatic handling of retain/release and still don't expose them to the public.
I have a console message that appears to be triggered by apparently unrelated events.
The message states:
snarfed from ivar layout: [propertyName] = [constantString]
Where [propertyName] is the name of a property to which I set the value of a string constant [constantString].
What causes this message and what does it means?
I also ran into this issue recently. I was able to fix my specific issue, but I don't think that is exactly what the questioners are running into, since my issue was only being exposed in VoiceOver mode. As such, I'll offer thoughts on what I think is generally occurring and then I'll speak to my specific issue.
As for the general issue, I think that the Apple Framework is deciding to look through all of the ivars of a particular class in order to extract some information that it wants, but that is not provided by other parts of the UI element. This seems a little bizarre to me, but that is what I encountered.
So, to continue with the general case, and in answer to the initial question. If you're like me, then your property name is probably the same as your ivar. Try explicitly defining a getter method for that property. Then, set a breakpoint within that getter if you will be returning a non-nil value. Look at the stacktrace and that should tell you which piece of the apple frameworks is deciding to loop through your ivar layout in order to get the information it wants. (If you're not using the the same name for your property and ivar, then just define a property and getter with the ivar name and do the same thing with the breakpoint.)
My specific case was for a Custom Table Cell (like one of the commenters). In that cell,I had a property that was the same name as its ivar. I also had an explicitly defined getter for that property. I also referenced that custom table cell from the Nib file. So, it looked something like this:
class CustomTableViewCell:UITableViewCell
{
NSString *s ;
}
#property(nonatomic,retain) NSString *s ;
and in the implementation:
#synthesize s ;
-(NSString *)s
{
if( !s )
return self.reuseIdentifer ;
return s ;
}
I put a breakpoint in the return self.reuseIdentifier line,and that showed me a stacktrace from the Accessibility functions. The stacktrace showed my method being called by an Apple internal method that was looping through all of my ivars looking for something to use as the accessibilityLabel for my table cell. The name of the selector is '_accessibilityRetrieveTableViewIvarsText'.
To make matter worse, in my case, this was not just a debugger issue, it was messing up my Accessibility interface by using the wrong thing as the accessibilityLabel.
I came up with 3 fixes for my specific problem:
1) I added a value for the accessibilityLabel for the table cell inside the Nib. This satisfied the Apple framework to the point where it did not go searching through my ivars. This was not the solution I went with, however, because I did not want a static accessibility label.
2) I subclassed my CustomTableViewCell with an empty implementation and interface, and I used that as my Table cell class inside the Nib. This solved the problem because the Apple Framework looped through that class's ivars, of which there were none, and there weren't any values to 'snarf'. I did not use that solution either, but it might be the best one because it keeps Apple's frameworks from inspecting my ivars.
3) The solution I decided on was to make my ivar private and to define the property with a different name. That seems to be the standard way that a lot of folks use properties. This is what it looks like:
class CustomTableViewCell:UITableViewCell
{
#private
NSString *_s ;
}
#property(nonatomic,retain) NSString *s ;
and in the implementation:
#synthesize s = _s ;
-(NSString *)s
{
if( !_s )
return self.reuseIdentifer ;
return _s ;
}
This fixed the problem because nil is returned when Apple inspects the ivar, and, thus, nothing is 'snarfed'. I'm still not sure whether this or #2 is more appropriate.
"snarfed from ivar" basically autofills your accessibilityLabel. If you do that yourself, the message goes away, as there is no more need for sneeking into your UITableViewCell.
For future reference. The message is logged by the accessibility framework, which apparently looks through an UIView ivars for strings.
If you have a custom subclass you can define the custom attributes as specified in the following link:
Accessibility Programming Guide
Alternatively you can make the view subclass not accessible:
- (BOOL)isAccessibilityElement
{
return NO;
}
However, note:
If your application contains a custom individual view with which users need to interact, you must make the view accessible.
In a project I have taken on, the original author has opted to use objc_setAssociatedObject() and I'm not 100% clear what it does or why they decided to use it.
I decided to look it up and, unfortunately, the docs aren't very descriptive about its purpose.
objc_setAssociatedObject
Sets an associated value for a given object using a given key and association policy.
void objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy)
Parameters
object
The source object for the association.
key
The key for the association.
value
The value to associate with the key key for object. Pass nil to clear an existing association.
policy
The policy for the association. For possible values, see “Associative Object Behaviors.”
So what exactly does this function do and in what cases should it be used?
Edit after reading answers
So what is the point in the following code?
Device *device = [self.list objectAtIndex:[indexPath row]];
DeviceViewController *next = [[DeviceViewController alloc] initWithController:self.controller
device:device
item:self.rootVC.selectedItem];
objc_setAssociatedObject(device, &kDeviceControllerKey, next, OBJC_ASSOCIATION_RETAIN);
What is the point in associating the device with the view controller if it's already an instance variable?
objc_setAssociatedObject adds a key value store to each Objective-C object. It lets you store additional state for the object, not reflected in its instance variables.
It's really convenient when you want to store things belonging to an object outside of the main implementation. One of the main use cases is in categories where you cannot add instance variables. Here you use objc_setAssociatedObject to attach your additional variables to the self object.
When using the right association policy your objects will be released when the main object is deallocated.
From the reference documents on Objective-C Runtime Reference:
You use the Objective-C runtime
function objc_setAssociatedObject to
make an association between one object
and another. The function takes four
parameters: the source object, a key,
the value, and an association policy
constant. The key is a void pointer.
The key for each association must be unique. A typical pattern is to
use a static variable.
The policy specifies whether the associated object is assigned,
retained, or copied, and whether the
association is be made atomically or
non-atomically. This pattern is
similar to that of the attributes of
a declared property (see “Property
Declaration Attributes”). You specify
the policy for the relationship using
a constant (see
objc_AssociationPolicy and
Associative Object Behaviors).
Establishing an association between an array and a string
static char overviewKey;
NSArray *array =
[[NSArray alloc] initWithObjects:#"One", #"Two", #"Three", nil];
// For the purposes of illustration, use initWithFormat: to ensure
// the string can be deallocated
NSString *overview =
[[NSString alloc] initWithFormat:#"%#", #"First three numbers"];
objc_setAssociatedObject (
array,
&overviewKey,
overview,
OBJC_ASSOCIATION_RETAIN
);
[overview release];
// (1) overview valid
[array release];
// (2) overview invalid
At point 1, the string overview is
still valid because the
OBJC_ASSOCIATION_RETAIN policy
specifies that the array retains the
associated object. When the array is
deallocated, however (at point 2),
overview is released and so in this
case also deallocated. If you try to,
for example, log the value of
overview, you generate a runtime
exception.
Here is a list of use cases for object associations:
one: To add instance variables to categories. In general this technique is advised against, but here is an example of a legitimate use. Let's say you want to simulate additional instance variables for objects you cannot modify (we are talking about modifying the object itself, ie without subclassing). Let's say setting a title on a UIImage.
// UIImage-Title.h:
#interface UIImage(Title)
#property(nonatomic, copy) NSString *title;
#end
// UIImage-Title.m:
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
static char titleKey;
#implementation UIImage(Title)
- (NSString *)title
{
return objc_getAssociatedObject(self, &titleKey);
}
- (void)setTitle:(NSString *)title
{
objc_setAssociatedObject(self, &titleKey, title, OBJC_ASSOCIATION_COPY);
}
#end
Also, here is a pretty complex (but awesome) way of using associated objects with categories.. it basically allows you to pass in a block instead of a selector to a UIControl.
two: Dynamically adding state information to an object not covered by its instance variables in conjunction with KVO.
The idea is that your object gains state information only during runtime (ie dynamically). So the idea is that although you can store this state info in an instance variable, the fact that you're attaching this info into a an object instantiated at runtime and dynamically associating it with the other object, you are highlighting the fact that this is a dynamic state of the object.
One excellent example that illustrates this is this library, in which associative objects are used with KVO notifications. Here is an excerpt of the code (note: this KVO notification isn't necessary to run make the code in that library work.. rather it's put there by the author for convenience, basically any object that registers to this will be notified via KVO that changes have happened to it):
static char BOOLRevealing;
- (BOOL)isRevealing
{
return [(NSNumber*)objc_getAssociatedObject(self, &BOOLRevealing) boolValue];
}
- (void)_setRevealing:(BOOL)revealing
{
[self willChangeValueForKey:#"isRevealing"];
objc_setAssociatedObject(self, &BOOLRevealing,
[NSNumber numberWithBool:revealing], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[self didChangeValueForKey:#"isRevealing"];
}
bonus: take a look at this discussion/explanation of associated objects by Mattt Thompson, author of the seminal AFNetworking library
To answer your revised question:
What is the point in associating the device with the view controller if it's already an instance variable?
There are several reasons why you might want to do this.
the Device class doesn't have a controller instance variable, or property and you can't change it or subclass it e.g. you don't have the source code.
you want two controllers associated with the device object and you can't change the device class or subclass it.
Personally, I think it is very rare to need to use low level Objective-C runtime functions. This looks like a code smell to me.
I'm certain that I'm missing some fundamental understanding of iOS memory management and, despite lots of reading and searching, I'm still not getting it.
I use a singleton in my app that has info about the user currently signed into it, info accessed from multiple view controllers, etc. It has multiple ivars that are get and set throughout the app. They're declared and propertied in the .h file like so:
NSString *myString;
and are made retained like so:
#property (non atomic, retain) NSString *myString;
and synththesized in the implementation.
I get and set their values in methods in the singleton like this:
myString = #"value";
and
methodLocalString = myString;
In other places I include the singleton -- call it CurrentUser -- I import it:
#import "CurrentUser.h"
Outside of the singleton I get and set it like this:
[CurrentUser sharedCurrentUser].myString = #"Bob";
and
myOutsideString = [CurrentUser sharedCurrentUser].myString;
Most of the time this works great, with the values appropriately persisted from one getting or setting to another. The trouble is that sometimes when I get them that way I find that they've been released (crashing the app), which NSZombieEnabled thankfully tells me.
What I don't get is how his can happen. I thought the singleton was never released, and that therefor retained properties of the singleton would never be released. I'll note that the problem seems to be more common with non-real-object properties like NSDate and definitely-not-object properties like int and BOOL which can't be retained, but it happens with object properties as well.
What am I ignorant about here? And thanks for your patience.
Your problem is:
I get and set their values in methods
in the singleton like this:
myString = #"value";
When you assign directly to the iVar, instead of using the property syntax (self.myString = #"value"), you are bypassing the synthesized setter method, which means that the retain never happens.
Properties aren't magic. They're just a bit of syntactic sugar for the "." access, and the ability to have synthesized getter/setter methods to save you the tedium of writing your own.
self.myString = #"value";
is just shorthand for
[self setMyString:#"value"];
The synthesized setMyString method will do something like:
if (myString != newValue) {
[myString release];
myString = [newValue retain];
}
(assuming retain option on the #synthesize)
Don't use singletons. Your current problem is caused by a simple memory management misconception, but the singleton pattern will only give you more headache in the long run.
First off, I despise singletons with a passion. Though I should probably be trying to use one, I just don't want to. I want to create a data class (that is instantiated only once by a view controller on loading), and then using a different class, message the crap out of that data instance until it is brimming with so much data, it smiles.
So, how do I do that? I made a pointer to the instance of the data class when I instantiated it. I'm now over in a separate view controller, action occurs, and I want to update the initial data object. I think I need to reference that object by way of pointer, but I have no idea how to do that. Yes, I've set properties and getters and setters, which seem to work, but only in the initial view controller class.
There's no need to use a singleton if you don't like the pattern or if it doesn't fit. Assuming you are creating your second view controller in the first one, just declare an ivar and property for your model object in your second view controller and when you instantiate it, assign the model object to this property.
Make a global variable for your object and store it there on creation. You can wire that up in the init method (probably bad style), or from the caller or via interface builder. Just make your variable known in the files that use it.
Or - well - use some kind of singleton pattern and get the instance directly from that class. Looks much cleaner.
Seriously use a singleton. In case you don't like them cause you don't know the code:
#interface Order : NSObject {
NSMutableArray *order;
}
#property (nonatomic, retain) NSMutableArray *order;
+ (Order *)sharedInstance;
#end
#import "Order.h"
#implementation Order
#synthesize order;
+(Order *)sharedInstance {
static Order *myInstance = nil;
#synchronized(self) {
if(!myInstance) {
myInstance = [[Order alloc] init];
}
}
return myInstance;
}
-(void)dealloc {
[order release];
[super dealloc];
}
#end
Um. Hello. Isn't Core Data a good enough framework for you? It allows you to have a single persistent store and multiple contexts to manage updates and merging of changes in response to notifications. I may be out of line here, but seeing how you start the question with a strong opinion about a well accepted pattern in your first question indicates that you have not spent much time discovering the ways in which the objective c runtime and Foundation classes in iOS can collaborate to achieve a task. In any software, one object and only one object owns a specific resource. You should embrace singletons. I suggest you spend some time reading http://www.cocoadesignpatterns.com/. Oh yeah, check out the meaning of KVO.
Why not make it a property of your app delegate? That way you don't have to use the singleton pattern but you are taking advantage of Apple's already existing usage of the singleton pattern.
Don't forget that Objective-C is a superset of C.
Basically, a data class is a plain C struct.
If you want to access a variable of that class from another class, make it global.
mydata.h:
struct MyData {
// Whatever data fields that you need, e.g.:
NSInteger value;
};
extern struct MyData mydata;
mydata.c:
struct MyData mydata = {
// Whatever initial value that you find relevant, e.g.:
.value = 42;
};