I have set up one of my core data attributes as a Boolean. Now, I need to set it, but XCode keeps telling me that it may not respond to setUseGPS.
[ride setUseGPS: useGPS.on];
What is the method for setting a boolean in core data? All my other attributes are set this way, and they work great. So, not sure why a boolean does not work to be set this way?
Core Data "does not have" a Boolean type (it does, but it is an NSNumber).
So to set the equivalent of useGPS = YES.
[entity setUseGPS:[NSNumber numberWithBool:YES]];
And the other way around:
BOOL isGPSOn = [[entity useGPS] boolValue];
Update:
As pointed out by SKG, With literals in Objetive-C you can now do it in a simpler way:
[entity setUseGPS:#YES];
BOOL isGPSOn = entity.useGPS.boolValue;
As an alternative approach to the accepted answer, you can simply change the typing from an NSNumber* to a BOOL in the managed object interface definition, such as:
#property (nonatomic) BOOL useGPS; // Notice that the 'retain' is also removed as we're now dealing with a scalar rather than an NSObject
Various alternative approaches are discussed here, but Chris Hanson's response was most illuminating for me, especially:
If you have a numeric attribute
(including a boolean attribute) that's
required, you can just type it as a
scalar instead, and Core Data will do
the right thing:
#property (nonatomic) BOOL isDone;
Even if the attribute is optional,
that'll still work - it'll just
conflate "not present" with "false."
and for a more aligned Cocoa implementation:
One other thing you might want to do
is name the property "done" and just
specify the getter as "isDone." That's
the usual Cocoa naming convention:
#property (nonatomic, getter=isDone)
BOOL done;
Then you can write "if (item.done) {
... }" or "item.done = NO;" and the
compiler will still generate -isDone
for accesses of the property.
Thanks Chris, and hope that this helps someone.
Just to complement #RickiG answer, the way to create a NSNumber from a Booland vice-versa in Swift (at least since v4.2) is:
let nsNumberFromBool = NSNumber(booleanLiteral: true) // or false
let boolFromNSNumber = nsNumberFromBool.boolValue
The "fix" for this (IMHO, it's a bug in Apple's SDK) is to add the following code to your CoreData-generated class. NB: if you do this in a category, in a separate file, then you don't have to re-copy/paste it each time you regenerate the CoreData classes inside Xcode
- (BOOL)useGPS
{
[self willAccessValueForKey:#"useGPS"];
BOOL myuseGPS = [[self primitiveUseGPS] boolValue];
[self didAccessValueForKey:#"useGPS"];
return myuseGPS;
}
- (void)setUseGPS:(BOOL)newValue
{
[self willChangeValueForKey:#"useGPS"];
[self setPrimitiveUseGPS:[NSNumber numberWithBool:newValue]];
[self didChangeValueForKey:#"useGPS"];
}
Related
I've recently discovered that there is no need to declare a getter as a property to use the dot notation. I don't know about other compiler versions, but this is true for Apple LLVM 3.1. Does anyone foresees any problems with it? So, basically:
---------Star.h----------
-(UInt32)age;
---------Star.m----------
-(UInt32)age
{
//get star age
return starAge;
}
---------RootViewController.m----------
{
...
//use this instead of [star age] even if there is no synthesized property "age"
NSLog(#"%i", star.age);
...
}
Your code is perfectly acceptable. A compiler wold do something similiar if you wrote:
---------Star.h----------
#property (readonly) UInt32 age;
---------Star.m----------
#synthesize age = starAge;
Your code is fine. Dot notation is just another way to invoke an instance method.
self.foo = bar; is the same as [self setFoo:bar];
bar = self.foo; is the same as bar = [self foo];
What does ARC make of that?
What happens if you try to compile :
- (void)setX:(NSInteger)x {
NSLog(#"New x is %i", x);
}
...
[self setX:100];
without declaring X as a property?
Even if it works I feel that it's good practice to add that simple extra line of code to declare it as a property even if all it does is make your code more readable.
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?
I've noticed that in a lot of the reference materials out there, I see that a lot of the time, variables are named _variable in the .h file, then are #synthesize'd in the .m file as
#synthesize variable = _variable;
Why is this done? What am I missing?
Thanks!
There is not consensus on this. Some people like to use it for clarity to separate out class variables, and as another responder noted to avoid conflict with incoming parameter names. Even in Apple sample code the use is mixed.
However, I greatly prefer to not use the _ prefix and have two strong reasons:
1) Some people think the _ is a good indicator of "private". My take is that NO class local variable should be accessed without a setter/getter (property) and thus they are ALL private - given that why not name them in a way easier to read and use autocomplete on? Any overlap in names from parameters is quickly revealed by the compiler, and avoided through more thoughtful naming of parameters (or internal variables).
2) (even better reason) - if you use "refactor" in XCode on an internal class var that is named the same as the property used to access it, the property and synthesize statement will also be renamed. If you use refactor on a class variable prefixed with an _, the property name will not be changed - just the synthesize mapping to the internal name. I pretty much never want the name to vary from the property to the real variable it exposes access to. That alone makes me never want to use _ as a variable prefix, since being able to shift names is just about the most useful thing you can do to improve code clarity.
Using that syntax is an option to make it more clear that the ivar and property are different things.
To code external to the class, there is no difference since it uses the property.
For code in the implementation of the class itself, it can make it more clear when the ivar is used versus the property.
For example, say we have an ivar/property for an NSNumber object:
#interface MyClass : NSObject {
NSNumber *num;
}
#property (nonatomic, retain) NSNumber *num;
- (void)doSomething;
#end
#implementation MyClass
#synthesize num;
- (void)doSomething {
// set the property, num is properly retained
self.num = [NSNumber numberWithInteger:1];
// accidentally set the ivar, num is NOT retained
num = [NSNumber numberWithInteger:2];
}
#end
and now using a different name for the ivar and property:
#interface MyClass : NSObject {
NSNumber *i_num;
}
#property (nonatomic, retain) NSNumber *num;
- (void)doSomething;
#end
#implementation MyClass
#synthesize num = i_num;
- (void)doSomething {
// set the property, num is properly retained
self.num = [NSNumber numberWithInteger:1];
// compiler error, there is no ivar named "num"
num = [NSNumber numberWithInteger:2];
// set the ivar, so it needs to be a retained object
i_num = [[NSNumber alloc] initWithInteger:3];
}
#end
Previous answers are missing the history behind this. Before Objective-C 2.0, there were no properties. So you’d have an object with instance variables like this:
#interface MyObject: NSObject {
NSArray *myArray;
}
#end
But how would you access them from other objects? the solution was to make setters and getters. But to avoid confusion, they would do it like this:
#interface MyObject: NSObject {
NSArray *_myArray;
}
- (NSArray *)myArray;
- (void)setMyArray:(NSArray *)myArray;
#end
The _ serves to clear up confusion between the instance variable _myArray and the method -myArray.
Sometimes people use mVarName (C++) and in Obj-c the style seems to be _varName.
One problem you can have, is imagine that your argument to a function is ...set:(int) x - BUT - you have an iVar called x...well your going to get the compiler crying about stuff like that - not to mention its confusing.
The m,_, whatever helps to show what are member properties of the class.
-(void) set:(int)x
{
x = x; // x is an ivar! heh
}
VS
-(void) set:(int)x
{
_x = x; // ahh I see!
}
This is purely convention. I suppose its common because when you make a method getter call like this:
[myObject variable]
you are actually calling a method, not accessing a variable directly. the _ in front makes it clear that you are talking about a variable. Personally, I find this syntax annoying and distracting. I find it unnecessary, but you are right, it does appear here and there.
I prefer not to use the '_' prefix because Apple does use it consistently. By avoiding the prefix I then have greater confidence that my ivars do not collide with Apple's when I extend a cocoa touch class. Since we do not have access to the base class' source this is really the only way I know of to avoid accidental reuse of existing private ivars.
Much like
Method names beginning with “_”, a single underscore character, are reserved for use by Apple.
My preference, following Google, is simply to append an underscore and explicitly synthesize (even if I'm reimplementing):
#synthesize varName=varName_;
If I see that trailing underscore outside of init..., dealloc or an accessor, I know something's fishy.
Update:
iPhone OS 3.1 has associated objects. However, the iPhone simulator does not. If you want to test associated objects code in the simulator, you should file a bug.
See my SO question here.
rdar://7477326
Snow Leopard now has associated objects.
Is there a way to accomplish something similar without associated objects? (Specifically for the iPhone.)
I am pretty sure I saw something like this a while back, but I can't remember where. Something about turning any object into a KVC container.
objc_setAssociatedObject() and friends were added to iPhone OS 3.1, so if you have the option of targetting just 3.1+ devices you can in fact do the exact same thing as on Snow Leopard...
If you can't you can create a static dictionary of associations and monkey patch out NSObjects dealloc method. For various technical reasons this solution cannot be made to work correctly in the presence of GC (which is why apple added the association stuff), but since iPhone does not support GC that is a non-issue.
If you are just starting work on this project I highly recommend using the runtime functions and targeting 3.1 plus, but if that is not an option here is an example of how you do it.
LGAssociativeStorage.h:
#import <pthread.h>
#import <Foundation/Foundation.h>
#interface NSObject (LGAssociativeStorage)
#property (retain) id associatedObject;
#end
LGAssociativeStorage.mm
#import <objc/runtime.h>
#import "LGAssociativeStorage.h"
/* We are using STL containers because:
1) Using Objective C containers can cause deallocs which cause recursion issues
2) STL containers are high perf containers that don't introduce external code dependencies
Ideally one could include a thread safe map implementation, but I don't need one currently
*/
#include <map>
typedef std::map<id,id> idMap_t;
typedef std::pair<id,id> idPair_t;
static NSMutableDictionary * data = nil;
static pthread_mutex_t data_lock = PTHREAD_MUTEX_INITIALIZER;
static IMP gOriginalNSObjectDealloc = nil;
static idMap_t associatedObjectMap;
static
void removeAssociatedObjectFromMap(id self) {
idMap_t::iterator iter = associatedObjectMap.find(self);
if( iter != associatedObjectMap.end() ) {
[iter->second release];
associatedObjectMap.erase(iter);
}
}
static
id newNSObjectDealloc(id self, SEL deallocSelector, ...) {
pthread_mutex_lock(&data_lock);
removeAssociatedObjectFromMap(self);
pthread_mutex_unlock(&data_lock);
return gOriginalNSObjectDealloc(self, deallocSelector);
}
static void initIfNecessary(void) {
if (!data) {
data = [[NSMutableDictionary alloc] init];
// The below line of code is abusive... in the future the Objective C runtime will use it as evidence
// that I am an unfit software engineer and take custody of all my code
gOriginalNSObjectDealloc = class_replaceMethod([NSObject class], #selector(dealloc), newNSObjectDealloc, "v#:");
}
}
#implementation NSObject (LGAssociativeStorage)
- (id) associatedObject {
id retval = nil;
pthread_mutex_lock(&data_lock);
initIfNecessary();
idMap_t::iterator iter = associatedObjectMap.find(self);
if( iter != associatedObjectMap.end() ) {
retval = iter->second;
}
pthread_mutex_unlock(&data_lock);
return retval;
}
- (void) setAssociatedObject:(id)object_ {
pthread_mutex_lock(&data_lock);
initIfNecessary();
removeAssociatedObjectFromMap(self);
[object_ retain];
associatedObjectMap.insert(idPair_t(self, object_));
pthread_mutex_unlock(&data_lock);
}
#end
You could always have them stored in a singleton.
There are no good ways to do this in a generic category.
You can easily add data for an object by having a global NSMutableDictionary that maps from any arbitrary NSObject to whatever data you want. The problem is there is no way to know when the object is deallocated, so you cannot tell (in general) when the data goes stale.
The only generic way to solve this is to use method swizzling to replace the NSObject dealloc method to report the deallocation of the object and release your associated data. I'm sure someone has done this, but its such a hideous hack it would be very hard to recommend as a valid appropach.
Now, if your objects in questions have some other way to monitor life cycle (ie, some deallocation hook, like a delegate objectWillClose method of some sort), then you can hook in to that to release your associated data and that would make the technique quite straight forward and legitimate.
I'll add an answer.
I found the original blog post, it was from Steve Degutis.
It basically involves replacing NSObject's methods for valueForUndefinedKey:, setValue:ForUndefinedKey:, and dealloc. Then using a static Dictionary to store any undefined keys.
Just about as nasty and fun as Louis's solution.
Notwithstanding concerns for concurrency issues, why not just use global variables ? Even using runtime objc_set/get AssociatedObject() methods aren't you passing a "global" static variable address in which case you still have concurrency issues wouldn't you?
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
This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How does an underscore in front of a variable in a cocoa objective-c class work?
I've seen this at Apple, inside UIPickerView.h:
id<UIPickerViewDataSource> _dataSource;
why's that underscore there? Does it have a special meaning? A Convention I must know about?
A lot of people use this for private variables, to differentiate between private variables and public variables within an object.
It is a completely optional way of working.
What you're seeing is the use of underlines to distinguish between instance variables and properties. So a class declaration might be:
#interface Foo {
NSString* _label;
....
}
#property (nonatomic, retain) NSString* label; // notice: no underline
Then in the implementation file you would have:
#synthesize label=_label; // the property is matched with the ivar
Now when inside the implementation, if you want to access the instance variable directly you could just use _label but to go through the property accessor methods (which take care of retain/releases and a bunch of other book-keeping tasks) you would use self.label. From the outside, you would always want to go through the {object}.label property.
The other way is to do without the underline and just use:
NSString* label;
#property (nonatomic, retain) NSString* label;
...
#synthesize label;
It works the same but then it might confuse someone reading the code and trying to keep track of label vs self.label. I personally find the Apple convention (with underlines) a bit easier to read but it's a matter of preference.
As people said already _someVar was used to say that a variable was private. It was a simple matter of convention and doesn't really matter.
One other use, taking a trip in the wayback machine in C a _function() represented a function that wasn't platform portable and __function() represented a function that wasn't compiler portable. So, in the standard C library, you will sometimes see a variable with a _ or __ infront of the name, this is what those functions represent.
It's sometimes used to denote private variables. More generally it just means "this variable is different somehow".
can it be that... (jogging memory)...
i vaguely remember reading an ADC document explaining that apple reserves the usage of underscore-prefixed member variables? and that 3rd party developers are discouraged from using this convention so as to avoid collisions?
|K<
I use underscores to denote that a variable is a member, similar to the 'm' prefix in Hungarian notation (which notation I despise thoroughly, but that's another story). Sure you get colour-coding editors these days, but my opinion is that the prefix makes you think about the variable being a member/instance one before you type it, not just sometime afterwards when it gets colour-coded by your editor.
Generally it's to denote that a variable should not be directly touched by a developer. It's not really a requirement but it's good practice if you can't avoid having a public variable in a class that you don't want messed with.
I choose to use underscores for ivars because I often come across the following situation:
#interface MyClass:NSObject
{
NSUInteger count;
}
#property(nonatomic) NSUInteger count;
-(id) initWithCount(NSUInteger) count;
#end
(...)
#implementation MyClass
#synthesize count;
-(id) initWithCount(NSUInteger) count
{
if((self = [super init])){
self.count = count; // Parameter name collides with ivar name!
}
return self;
}
#end
So I do this:
#interface MyClass:NSObject
{
NSUInteger _count;
}
#property(nonatomic) NSUInteger count;
-(id) initWithCount(NSUInteger) count;
#end
(...)
#implementation MyClass
#synthesize count = _count;
-(id) initWithCount(NSUInteger) count
{
if((self = [super init])){
_count = count; // No name collision
}
return self;
}
#end
Of course, I could alternatively change the parameter name to "newCount" or "aCount" (I hate that one). I think it's a matter of taste.