I am using CoreData in an iOS application. Everything works fine except for fields marked as Boolean in xcdatamodel that get modeled and NSNumber.
For this kind of fields I want to write some utility method in extended class, but I was wondering where's the best location for writing them or what's the best practice.
In MyManagedObject.h I have:
#interface MyManagedObject : NSManagedObject {
#private
}
#property (nonatomic, retain) NSNumber * mandatory;
#end
Where mandatory is a boolean in data model. This is the generated class from xcode:
#implementation MyManagedObject
#dynamic mandatory;
At this point, for properly using the entity I need to write somewhere some utility wrapper methods, probably in the entity itself, such as:
[myManagedObject mandatoryWrapper:YES];
-(void)mandatoryWrapper:(BOOL)mandatory {
// convert boolean to number
self.mandatory=convertedMandatory;
}
But I am aiming to use the original getter/setter for not generating "confusion":
// setter
myManagedObject.mandatory=YES;
//getter
if(myManagedObject.isMandatory)
but I suppose that rewriting the original methods, will cause some problem later on in the application lifecycle, for example when saving or retrieving in context.
thanks.
If you want a true boolean property, then your are forced to change the name. I would recommend just making the it a property of the class and not the entity because the entity doesn't have to know about them.
In your case, you would need something like:
#property BOOL isMandatory;
-(BOOL) isMandatory{
return [self.mandatory boolValue];
}
-(void) setIsMandatory:(BOOL) boolVal{
self.mandatory=[NSNumber numberWithBool:boolVal];
}
This lets you use convience constructions like:
If (self.isMandtaory)...
self.isMandatory=YES;
Core Data is happy because the entity modeled NSNumber property is still there and works as expected but the human can use the easier to comprehend boolean version.
Related
I looked up my current problem on stackoverflow and many other website outlets, but I am a little confused to be quite honest. Should I only use properties when another class needs access to it and ivars when it is being used for only my private class? This is what I am getting so far, although I did hear some other things about when to use ivars and properties. I am just trying to keep my code clean and more modern. Any clarification will be appreciated.
This is a very opinion based topic. So I'm trying to stay with uncontroversial facts and advice:
Never access ivars from outside of the class. Public access would always be done through properties and their accessors or other methods. Nowadays headers should never contain ivar declarations.
Using ivars internally is possible and not uncommon. ARC makes this easy for object types, as ownership is handled automatically.
Using properties gives you proper ownership handling for NSString, NSArray et al. (copy).
Also, in some cases they can help with thread safety (atomic).
Using properties internally could make KVO compliance or other side effects easier to implement.
Using private properties is the standard pattern for exposing IBOutlets.
Properties can be queried during runtime. This is seldom needed, though.
Private properties have the problem of polluting the method namespace for a class. Unintentional overrides can occur.
The actual decision whether or not to use ivars in the implementation is a matter of personal preference. It is affected by many subtle details from code style.
In my opinion - you should only use properties, which are backed by an ivar if you didn't override the getter and the setter.
You should declare them in the public interface to make them public, and declare them in the private interface, that's right, to make them private.
There are many advantages to this, some are:
Perform lazy instantiation in the getter
Do validation in the setter
Make a property readonly public and readwrite privately
Within your class, you should almost always access your properties through the getter/setter unless:
You want to avoid the behavior you implemented in these methods (lazy instantiation, validation)
You are in the initializer
You are in the getter/setter
Here's an example of how of some of the following points:
#interface SomeObject : NSObject
#property (strong, nonatomic) NSMutableArray * objects;
#property (readonly, nonatomic, getter=isActive) BOOL active; // Public read-only
#end
#interface SomeObject()
#property (readwrite, nonatomic, getter=isActive) BOOL active; // Can be updated internally
#property (nonatomic, getter=isVisible) BOOL visible;
#end
#implementation SomeObject
- (NSMutableArray)objects {
if (!_objects) {
_objects = [NSMutableArray array]; // Lazy instantiate when first accessed
}
return _objects;
}
- (BOOL)isActive {
return _isActive && self.isVisible; // Cannot be active if not visible
}
- (BOOL)setActive:(BOOL)active {
self.visible = active; // Keep visibility same as active
_active = active;
}
-(BOO)setVisible:(BOOL)visible {
_visible = visible;
// perform animation or something else...
}
#end
Any of this cannot be achieved using ivars.
You should use declared properties inside and outside your class. Most developers say that you should only set the ivar behind a property in initializers. (I do not agree and use setters and getters in this case, too, but I'm in minority.)
I've got a quickie today. Say I have a class called BSDHistoryManager. It's a simple state history recorder like in a web browser (aka a History object [window.history]). Here are simplified examples of the .h/m files:
BSDHistoryManager.h
#interface BSDHistoryManager : NSObject
#property (nonatomic, copy) NSArray *states;
#end
BSDHistoryManager.m
#implementation BSDHistoryManager {
NSMutableArray *_states;
}
- (NSArray *)states
{
return _states.copy;
}
- (void)setStates:(NSArray *)states
{
if ( [states isEqualToArray:_states] )
return;
_states = states.mutableCopy;
}
#end
As you can see, I have a standard mutable collection on the inside which is copied when accessed with the getter so the internals don't get messed up. At this point, I want to add some public accessor methods like -addState:, -removeState:, etc. For example, I like to make my own accessors like this:
- (void)addState:(BSDState *)state;
- (void)insertState:(BSDState *)state atIndex:(NSUInteger)index;
However, I want to define KVC methods, too. You know, the ones that look like this:
- (void)addStatesObject:(id)object;
- (void)insertObject:(id)object inStatesAtIndex:(NSUInteger)index;
Now I have both, and that's cool, but I want my class interface to be nice and clean, so it's easier to read and understand. My question is: when implementing the KVC accessor patterns, do I need to declare those methods or do I get KVC-compliance "for free" by just implementing the methods? Or a better question is: do I even need to implement the KVC methods if I make my own custom-named ones?
Hopefully this makes sense, but if not, I'll try to explain it a little better. Thanks for reading!
This is for a ORM.
I have a class Invoice that have a Customer property:
#interface Invoice : DbObject {
}
#property (nonatomic,strong) Customer *customer; //Customer is a DbObject
#property (nonatomic) NSInteger user;
#end
I have several instances of this. Now, how I can instantiate on demand a DbObject property with obj-c? I don't wanna to code each getter for all the cases, but do it in a generic way, like with python and overriding def __getattr__(self, attr).
I don't wanna to code each getter for all the cases
So, what you're saying is, when a call like anInvoice.customer is made, your Invoice class should do something to provide the instance which is more or less a template - it works more or less the same way for customer and for zingleberry, in a way that can be worked out from the name.
The way to deal with something like this is not to implement the getter (and prevent it from being synthesized), and to allow resolveInstanceMethod: to be called. At that point you can generate the getter with classAddMethod through a templating method that behaves in accordance with the name of the method originally called.
I really never used that and am curious whether it will work at all, but the reference manual even has some snippets for that. Please report back if it really works. This is very interesting.
https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSObject_Class/Reference/Reference.html#//apple_ref/occ/clm/NSObject/resolveInstanceMethod:
(Sorry, the : is not included into link by SO site engine, you have to append it manually or scroll down a little)
I am not 100% sure what you want... but you can overwrite a getter to make it lazy.
#property (nonatomic,strong) Customer *customer; // in .h
-(Customer *) customer // in .m
{
if(! _customer) //or whatever ivar you are using
{
_customer = [Customer new]; // or whatever you do to create the customer from the DB
}
return _customer;
}
you can also specify a different name for the getter with:
#property (nonatomic,strong,getter=myCustomer) Customer *customer; // in .h
the default setter will still be created.
you dont need to create getter/setter for any object. Use can directly use them using
object.customer.
I'm still new to Objective-C and I recently learned how to make properties, so far so good, but one thing that bothers me is that the setter and getter methods are still publicly available even after the property is made.
let's say I have the following code:
// myClass.h
#interface myClass : NSObject {
int _startPos;
}
#property (assign, readwrite, setter = setStartPos:, getter = getStartPos) int startPos;
-(void) setStartPos: (int) pos;
-(int) getStartPos;
#end
the implementation file should be rather self-explanatory, I'm not trying to do anything specific.
Now, I read somewhere, and tried it in practice that if you make a category in the implementation file, and add some methods to that, it's possible to make those methods invisible (aka private) to things outside of the myClass.m file.
"Alright" I think, and decide to try it out:
//myClass.m
#import <Foundation/Foundation.h>
#import "myClass.h"
#interface myClass (hidden)
-(void) setHiddenStartPos: (int) hPos;
-(int) getHiddenStartPos;
#end
#implementation myClass (hidden)
-(void) setHiddenStartPos: (int) hPos {
_startPos = hPos;
}
-(int) getHiddenStartPos {
return _startPos;
}
#end
#implementation myClass
-(void) setStartPos: (int) Pos {
[self setHiddenStartPos: Pos];
}
-(int) getStartPos {
return [self getHiddenStartPos]; //this is to see if I can get the value from the hidden methods through the non-hidden ones
}
#end
that's all fine, and testing it in main() I can see that the methods with "hidden" in their name are in fact inaccessible, and therefore act as if they are private.
Then I tried to add this to the header file:
#property (assign, readwrite, setter = setHiddenStartPos:, getter = getHiddenStartPos) int
to see if I could access the hidden methods through the property
but when I did that, the hidden methods became accessible in main() and the whole plan with making the methods only accessible through the property went down the drain
So I ask you, is there a way to make methods inaccessible to anything BUT the property and/or the object itself?
Edit: I realize that getters don't usually have get in the name, so please stop commenting on it?
also to emphasise what I meant:
I wanted to make properties like in c#, where the content of the setters and getters are private to the property itself
public int exampleProperty
{
set{...}
get{...}
}
it doesn't use methods as getters and setters, and therefore the code in the setters and getters are accessible to only the property, JUST like the code within a method is local to the method itself
Add a class continuation in your .m file. i.e.:
#interface myClass ()
#property (assign, readwrite, setter = setHiddenStartPos:, getter = getHiddenStartPos) int hiddenStartPos;
#end
#implimentation myClass
#synthesize hiddenStartPos = _hiddenStartPos;
...
#end
Have a look at: What is an Objective-C "class continuation"?
PS: Your getters should just be hiddenStartPos rather than getHiddenStartPos...
It seems to me that the your confusion comes from misunderstanding exactly what an #property declaration is. It is essentially a declaration that setter and getter methods exist.
So, this
#property int hiddenStartPos;
is the same as this
- (int)hiddenStartPos;
- (void)setHiddenStartPos;
So, the implementation of these two methods is the implementation of the property. By decaring the property in the .h file, you're advertising to anyone who imports the .h that the class in question implements these two methods (the getter and the setter, respectively).
I also want to reemphasize that getter methods should not be prefixed with "get" in Objective-C.
You're over-thinking what "private" means. In ObjC, "private" just means "not visible." It doesn't mean "not callable." The way you make a method private is to not put it in your .h file, which declares your public interface.
There is no way to control who passes a message. This is a key fact of ObjC and cannot (and should not) be changed. ObjC is a dynamic language. At runtime, I am free to generate selectors and call performSelector: on any object I want. Anything that stopped that would either (a) introduce significant performance penalties, or (b) break many very useful and common techniques in ObjC (probably both). ObjC is not Java or C#. It's not even C or C++. It's Smalltalk on top of C. It's a highly dynamic language and that has a lot of strengths. Unlearning other languages is the first step towards becoming a good Cocoa developer.
It would be nice to have a compiler-checked #private for methods (of which properties are just a special case), and it would especially be awesome to have a compiler-checked #protected for methods (these exist for ivars). These would make it slightly simpler to avoid some kinds of mistakes. But that's the only way you should be thinking about this. The goal is not to protect one part of the code from another part of the code. The other code is not the enemy. It's all written by people who want the program to work. The goal is to avoid mistakes. Correct naming, consistency, and the absolute elimination of warnings is how you achieve that in ObjC.
So yes, I'd love to be able to put #protected in front of my #property declarations occasionally. Today you can't, and there is no real equivalent (I sometimes use a +Protected category in a separate header, but it's generally more trouble than its worth). But that said, having it wouldn't change very much, and I only find a case where I would even use this a few times a year. I can't think of single case where #private for a method would have been really useful, though.
Can custom property attributes be created in Objective-C just like in VB.NET? For example, in VB.NET you can create the "Browsable" attribute and read it at runtime to determine whether you should display a property or not.
Public Class Employee
<Browsable(True)> _
Public Property Property1() As String
Get
End Get
Set(ByVal Value As String)
End Set
End Property
<Browsable(False)> _
Public Property Property2() As String
Get
End Get
Set(ByVal Value As String)
End Set
End Property
End Class
I would like to do the same in Objective-C, even if it is a fixed attribute that can only be set at compile time and cannot be changed at all.
What I'm trying to do is to add an attribute to properties of my class to determine whether the properties should be serialized or not.
I know the standard Objective-C attributes (readonly, nonatomic, etc.), but those don't help me... unless you have a creative way of using them. I also looked into using C attributes with the __attribute__(("Insert attribute here")) keyword, but C has specific attributes that serve specific purposes, and I'm not even sure you can read them at runtime. If I missed one that can help me, let me know.
I tried using typdef. For example:
typdef int serializableInt;
serializableInt myInt;
and use the property_getAttributes() Objective-C runtime function, but all it tells me is that myInt is an int. I guess typedef is pretty much like a macro in this case... unless I can create a variable of type serializableInt at runtime. Anyhow, here's Apple's documentation on the values you get from property_getAttributes().
The other requirement is that this attribute has to work with NSObject sub-classes as well as primitive data types. I thought about the idea of adding to the class a black lists or white lists as an ivar that would tell me which properties to skip or serialize, which is basically the same idea. I'm just trying to move that black/white list to attributes so it's easy to understand when you see the header file of a class, it's consistent across any class I create and it's less error prone.
Also, this is something to consider. I don't really need the attribue to have a value (TRUE or FALSE; 1, 2, 3; or whatever) because the attribute itself is the value. If the attribute exists, then serialize; otherwise, skip.
Any help is appreciated. If you know for sure that this is not possible on Objective-C, then let me know. Thanks.
If you want to add attribute to property, class, method or ivar, you can try to use github.com/libObjCAttr. It's really easy to use, add it via cocoapods, and then you can add attribute like that:
#interface Foo
RF_ATTRIBUTE(YourAttributeClass, property1 = value1)
#property id bar;
#end
And in the code:
YourAttributeClass *attribute = [NSDate RF_attributeForProperty:#"bar" withAttributeType:[YourAttributeClass class]];
// Do whatever you want with attribute, nil if no attribute with specified class
NSLog(#"%#", attribute.property1)
unless i've missed your point…
i'd recommend declaring a protocol. then using instances of objc objects as variables in your objc classes which adopt the protocol.
#interface MONProtocol
- (BOOL)isSerializable;
- (BOOL)isBrowsable;
/* ... */
#end
#interface MONInteger : NSObject <MONProtocol>
{
int value;
}
- (id)initWithInt:(int)anInt;
#end
#interface MONIntegerWithDynamicProperties : NSObject <MONProtocol>
{
int value;
BOOL isSerializable;
BOOL isBrowsable;
}
- (id)initWithInt:(int)anInt isSerializable:(BOOL)isSerializable isBrowsable:(BOOL)isBrowsable;
#end
// finally, a usage
#interface MONObjectWithProperties : NSObject
{
MONInteger * ivarOne;
MONIntegerWithDynamicProperties * ivarTwo;
}
#end
if you want to share some implementation, then just subclass NSObject and extend the base class.
you'd then have a few variants to write for the types/structures you want to represent.
The deficiency with the other answers I've seen so far is that they are implemented as instance methods, i.e., you need to have an instance already before you can query this metadata. There are probably edge cases where that's appropriate, but metadata about classes should be implemented as class methods, just as Apple does, e.g.:
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString*)key { }
We could imagine our own along similar lines:
+ (BOOL)keyIsBrowsable:(NSString*)key { }
or
+ (NSArray*)serializableProperties { }
Let's imagine our class is called FOOBar, and we want to know whether the baz key is browsable. Without having to create a FOOBar we can just say:
if ([FOOBar keyIsBrowsable:#"baz"]} { ... }
You can do pretty much anything with this technique that can be done with custom attributes. (Except for things like the Serializable attribute which require cooperation from the compiler, IIRC.) The nice thing about custom attributes, though, is that it is easy to distinguish at a glance what is metadata and what is intrinsic to that class's actual functionality, but I think that's a minor gain.
(Of course, you may have to check for the existence of the keyIsBrowsable: selector, just as you'd have to check for the existence of a specific custom attribute. Again, custom attributes have a slight leg up here, since we can tell the .NET runtime to give them all to us.)
I've come across a similar issue whe serializing objects. My solution is to add a #property (nonatomic, readonly) NSArray *serialProperties; which has a custom getter that returns the names (as NSString*) of the properties of this (sub-)class that should be serialized.
For example:
- (NSArray *)serialProperties {
return #[#"id", #"lastModified", #"version", #"uid"];
}
Or in a subclass:
- (NSArray *)serialProperties {
NSMutableArray *sp = [super serialProperties].mutableCopy;
[sp addObject:#"visibleName"];
return sp;
}
You can then easily get all properties and their values via [self dictionaryWithValuesForKeys:self.serialProperties].
You can't add custom properties other than what sdk has provided..
.
But there is a work around to attain your objective...
#interface classTest:NSObject
#property(strong,nonatomic)NSString *firstName;
#property(strong,nonatomic)NSString *lastName;
#property(strong,nonatomic)NSMutableDictionary *metaData;
#end
#implementation classTest
- (id) init
{
self = [super init];
//Add meta data
metaData=[[NSmutableDictionary alloc]init];
//
if( !self ) return nil;
return self;
}
#end
so use the dictionary to add and retrieve meta data...
i hope it helps....