Can transformable attributes in Core Data entities be pointers to c structs? My transformer is not being called - objective-c

I'm trying to make a CoreData-persisted entity. This entity has a few properties, one of which is a non-standard attribute, state. The state attribute is a pointer to a C struct with a few properties in it. Here's what my data model looks like:
Entities:
MDInstance
Attributes:
duration: Integer 16
moves: Integer 16
name: String
state: Transformable. I set the Transformer to MDStateTransformer.
I generated my class and edited the state property. This is what the interface looks like:
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "MDState.h" // this is where the State structure is defined
#interface MDInstance : NSManagedObject
#property (nonatomic, retain) NSNumber * duration;
#property (nonatomic, retain) NSNumber * moves;
#property (nonatomic, retain) NSString * name;
#property (nonatomic) State *state; // note that this is a pointer to a struct
#end
This is what the implementation looks like:
#import "MDInstance.h"
#implementation MDGameInstance
#dynamic duration;
#dynamic moves;
#dynamic name;
#synthesize state;
#end
I created a value transformer called MDStateTransformer. The implementation of this is (probably) not important. Suffice it to say I have allowsReverseTransformation returning YES, transformedValueClass returning [NSValue class], and I've implemented transformedValue: and reverseTransformedValue:
Lastly, I registered the MDStateTransformer in my AppDelegate's application:didFinishLaunchingWithOptions: like this:
MDStateTransformer *transformer = [[MDStateTransformer alloc] init];
[NSValueTransformer setValueTransformer:transformer forName:#"MDStateTransformer"];
If I create a new instance of my MDInstance, set it's attribute -including the state attribute- and then try to save the entity, my transformer is never called.
I put a stop point in my transformer's init method and it is being instantiated. I put another in transformedValue: and it the function is not being called.
However, if I update my MDInstance so that the state attribute is not a pointer, but is simply a State structure, and I update the transformer to work with a struct and not a pointer, the transformedValue: is called.
Is it possible to have a custom attribute on an object which is a pointer to a c struct? If so, any ideas what I'm doing wrong?

Your transformable attribute also needs to be specified as #dynamic and not #synthesize in your implementation file. By synthesizing that property you provide an getter and setter outside of core data and thus the Core Data provided accessors will not be used.

Related

Hiding privately mutable properties behind immutable interfaces in Objective-C

So, what I basically want to ask is whether the following code is safe (not whether it works, because it does). I.e, will the public getter override the synthesized getter of the actionLog property [which is of a different type]?
.h file:
#interface SomeClass : NSObject
- (NSArray*) actionLog;
#end
.m file:
#interface SomeClass ()
#property (strong, nonatomic) NSMutableArray* actionLog;
#end
#implementation SomeClass
...
#end
This is not only OK, it is exactly why class extensions were created in the first place!
Yes, there will be a single automatically synthesized ivar and pair of getter/setter methods generated as expected.
Sorry -- missed the NSArray vs. NSMutableArray part. No, you can't do that; the types must be the same.
However, you don't want to return your mutable array anyway. First, the caller might modify it (a bug). But, more importantly, the caller will assume that the contents are immutable as implied by the API) and, thus, when that array's contents change out from under the caller, it may cause issue (example; caller can reasonably assume that the result of count will be stable and can be cached).
By backing the property with a mutable ivar, like this:
.h file:
#interface SomeClass : NSObject
#property (nonatomic, strong) NSArray *actionLog;
#end
.m file:
#implementation SomeClass{
NSMutableArray* _actionLog;
}
-(void)insertAction:(Action *)action{
if(!_actionLog){
_actionLog = [[NSMutableArray alloc] init];
}
[_actionLog addObject:action];
}
#end

What to use for Objective-C objects instead of structs when using ARC?

ARC forbids Objective-C objects in structs or unions.
Unless you add __unsafe_unretained which means its not managed.
I was wonder what people are using in place of structs now if anything?
Or are you retaining everything manually?
It's very simple - if you want to add an object inside a struct, you are doing it wrong. Whenever you need a struct to hold an obj-c object, convert the struct into an obj-c object.
I would manage different objects in one objc-object like this:
#class MyFirst, MySecond;
#interface MyContainer : NSObject
#property (nonatomic, strong, readonly) MyFirst *firstInst;
#property (nonatomic, strong, readonly) MySecond *secondInst;
// optional: convenience initializer
+ (instancetype)containerWithFirstInst:(MyFirst *)firstInst secondInst:(MySecond *)secondInst;
#end
// required by linker: stub definition for the class declared above
#implementation MyContainer
#end
#interface SomeController : NSObject
- (void)doSomething;
#end
#implementation SomeController
- (void)doSomething {
MyFirst *firstInstance = [[MyFirst alloc] initWithSomeParameters:...];
MySecond *secondInstance = [[MySecond alloc] initWithSomeParameters:...];
MyContainer *container = [MyContainer containerWithFirstInst:firstInstance secondInst:secondInstance];
// use container as a struct (but it's definitely an object that is managed by ARC)
}
#end
Wouldn't it be a lot easier to implement a static class and fake its properties, as shown here?
I answered to it here https://stackoverflow.com/a/28845377/1570826
maybe somebody with the right level could mark this or the other as a duplicate.

Objective C: Should I assign the variable AND create a property or is just one of them enough?

I have got a header file (.h) and I want to declare name but all these ways work the same I think because I haven't seen any difference with functionality. Could you tell me what the difference is between:
This with both declarations:
#interface someClass : UIViewController
{
NSString *name;
}
#property (nonatomic, copy) NSString *name;
#end
Without variable:
#interface someClass : UIViewController
{
}
#property (nonatomic, copy) NSString *name;
#end
Or Without property:
#interface someClass : UIViewController
{
NSString *name;
}
#end
#interface someClass : UIViewController
{
NSString *name;
}
#property (nonatomic, copy) NSString *name;
#end
Doing this you will explicitly declare both a property and an ivar.
A property is just a set of methods:
- (void)setName:(NSString*)name;
- (NSString*)name;
An ivar is the memory store holding the value that the property methods manage. This allows you to do:
self.name = ... // access through setter method
name = ... // direct access
The advantage of using properties is that they deal with memory management for you. E.g., in your case, the property is of type copy: this means that with the first syntax (self.name = ...) a copy of the object will be done. If not using properties, you would explicitly need to do: name = [originalString copy]; to obtain the same effect.
Other options you can specify for properties (but not ivars) are: strong and weak ownerships.
Furthermore, a property also represents a public interface to access the variable from outside your class.
Using direct access you are on your own as to memory management (if you are not using ARC).
If you are using ARC and don't define properties, you will not be able to control how the memory is managed by specifying the ownership: strong, weak, retain).
#interface someClass : UIViewController
{
}
#property (nonatomic, copy) NSString *name;
#end
Here you only declare the properties; the ivar is "inferred" by the #synthesize directive in your implementation file. This is only possible in Objective C 2.0 and later (previously, the ivar declaration as above was mandatory).
The same considerations as above applies, with a minor nuance: with older versions of LLVM (ObjC compiler) you will not be able to reference directly the auto-synthesized ivar; with current version of LLVM, if you omit the #synthesize directive, then an automatic ivar named after your property would also be declared (in your case it would be _name).
This last paragraph may seem a bit "advanced", or contrived, but you can safely ignore it.
#interface someClass : UIViewController
{
NSString *name;
}
#end
In this case you are only declaring the ivar. No accessor methods. You will need to handle memory management on your own (if not using ARC), futhermore you will not be able to access the variable from outside the class. For that you need accessors.
Hope this helps.
Case 1:
The is the old method, here the #property and variable are not related until you #synthesize name = name;
Access methods :
variable : name = #"hello"; //direct access to viariable
setter/getter : self.name = #"hello" // set value to name using setName: selector
With the latest xcode just the property is enough.
Case 2:
the new xcode style. Here the synthesize and variable creation is taken care by the compiler. (so less 2 lines of code and this also helps with memory management)
Access methods :
variable : _name = #"hello"; //direct access to viariable
setter/getter : self.name = #"hello" // set value to name using setName: selector
Case 3:
Here the name is just a variable and it dose not have a setter or a getter.
with out property (or) setter & getter this is as good as a local variable and it cannot be accessed from other objects.

#property and #synthesize

I'm very new to Objective C. (Two days now). When read about #synthesize, it seemed to overlap with my understanding #property (which I thought I understood) ... So, some details need to be ironed out in my mind ... it's bugging me.
Please correct me if I'm wrong about differences of #property and #synthesize:
If you declare a #property in your #interface, then you're telling the world that users can expect to use standard getters and setters for that property. Futhermore, XCode will make generic getters and setters for you. ... BUT, To what degree does that happen with the #property declaration? ( I.E. does that mean "completely" ... like unseen declarations for it in your #interface, and also unseen code in your #interface?
-Or-
Does #property take care of the unseen code declarations in your #interface only - whereas #synthesize takes care of the unseen code implementation in your #implementation section? )
First, note that the latest version of Xcode does not require #synthesize at all anymore. You can (and should) just omit it. That said, here's what the pieces do.
#property is a declaration of accessors. It is just a declaration. There is very little difference between the following:
#property (nonatomic, readwrite, strong) NSString *something;
vs.
- (NSString *)something;
- (void)setSomething:(NSString)aSomething;
The main difference is that declaring these methods using #property lets the compiler automatically generate (synthesize) the implementations for you. There is no requirement that you let the compiler do it for you. You are absolutely free to implement something and setSomething: by hand, and it is common to do. But, if you don't implement them by hand, the compiler will automatically create an ivar for you called _something and create a reasonable implementation for the getter and setter.
In older versions of Xcode, you had to explicitly request the auto-generation using the #synthesize keyword. But that is no longer required. Today, the only reason to use #synthesize is if you want the ivar to have a non-standard name (never do that).
A key point here is that the methods something and setSomething: are just methods. There is nothing magical about them. They're not special "property methods." They're just methods that by convention access a piece of state. That piece of state is often stored in an ivar, but does not need to be.
To be even more clear: object.something does not mean "return the ivar named _something from object." It means "return the result of [object something], whatever that does." It is common for that to return the value of an ivar.
You should declare all of your state (internal and external) using #property declarations, and you should avoid directly declaring ivars. You should also always access your properties via their accessors (self.something), except in the init and dealloc methods. In init and dealloc, you should directly use the ivar (_something).
#property declares a property on your class with whatever atomicity and setter semantics you provide.
With Xcode 4.4, autosynthesis is available wherein you are provided with a backing ivar from your property without declaring it in #synthesize. This ivar has the form of _propertyName where your property name is propertyName.
Objective-C #property and #synthesize
#property
generates get/set method
today(from Xcode v4.4 with the LLVM v4.0) #property additionally uses #synthesize inside
#synthesize propertyName = _propertyName
#synthesize:
generates a new iVar or link with existing iVar
generates an implementation of the get/set method with an appropriate iVar
[Case when #synthesize can be used]
#property
#interface SomeClass : NSObject
#property NSString *foo;
#end
//generated code
#interface SomeClass : NSObject
- (NSString *)foo;
- (void)setFoo:(NSString)newFoo;
#end
#synthesize pattern
#synthesize <property_name> = <variable_name>;
//Using
//1. Specify a variable. New variable(variableName) will be generated/linked with existing
#synthesize propertyName = variableName
//if variableName is not exist it generates:
//NSString *variableName;
//read access
NSString *temp = variableName;
//2. Default. New variable(propertyName - the same name as a property) will be generated/linked with existing
#synthesize propertyName
//is the same as
//#synthesize propertyName = propertyName
//if propertyName is not exist it generates:
//NSString *propertyName;
//read access
NSString *temp = propertyName;
//if you specify not-existing <property_name> you get
//Property implementation must have its declaration in interface '<class_name>' or one of its extensions
previously you had to use next syntax:
#interface SomeClass : NSObject
{
//1. declare variable
NSString *_foo;
}
//2. create property
#property NSString *foo;
#end
#implementation SomeClass
//3. link property and iVar
#synthesize foo = _foo;
#end
But today you can use next syntax
#interface SomeClass : NSObject
//1. create property
#property NSString *foo;
#end
Next, the same code, will be generated for both cases
#interface SomeClass : NSObject
{
//variable
NSString *_foo;
}
//getter/setter
- (void)setFoo:(NSString *)newFoo;
- (NSString *)foo;
#end
#implementation SomeClass
- (void)setFoo:(NSString *)newFoo
{
_foo = newFoo;
}
- (NSString *)foo
{
return _foo;
}
#end

inherit an immutable copy property as mutable retain

I am having the following code:
#interface Room : NSObject
{
#protected
NSMutableDictionary* mCustomProperties;
}
#property (readonly, copy) NSDictionary* CustomProperties;
#end
#interface MutableRoom : Room
{
}
#property (readwrite, retain) NSMutableDictionary* CustomProperties;
#end
These properties are then implemented later by accessing mCustomProperties.
I know, that it is not allowed to redeclare the memory management attribute or the data type of a property in a subclass to differ from the ones in the base class.
However, I want to achieve the following:
- Give only readonly access to the dictionary in the immutable base class. As the member is a NSMutableDictionary, just returning it as a retained instance of NSDictionary would mean, that it simple cast would make it mutable again, even unintended, when the user of the property stores the access variable somewhere as an NSObject instance and then recovers the original type of it back later. Therefor I want to return the mutable dictionary by immutable copy in the readonly property.
- Give full readwrite access to the dictionary in the mutable sub class. As you should not only be able to store another dictionary there, but also to just change the content of the existing one, I would like the property in the subclass not only to be readwrite, but also to be retained, instead of copied, so that the original values will be accessed, and to access it as an NSMutableDictionary, not as a NSDictionary, so that one can add, remove or change entries of the dictionary through the property.
Is there any more elegant way than suppressing the warning or using two differently named properties?
when declaring a mutable/immutable pair of a class cluster, i often find it simplest to not inherit from another, but to use an inner class for the implementation, like so:
// Room.h
#interface Room : NSObject
// ...
#end
#interface MutableRoom : Room
// ...
#end
// MONRoom.h
#class RoomImp;
#interface MONRoom : Room
{
#private
RoomImp * imp;
}
#property (readonly, copy) NSDictionary* CustomProperties;
#end
#interface MONMutableRoom : MutableRoom
{
#private
RoomImp * imp;
}
#property (readwrite, retain) NSMutableDictionary* CustomProperties;
#end
// RoomImp.h
#interface RoomImp : NSObject
{
#private
NSMutableDictionary* mCustomProperties;
}
// ...
#end