NSManagedObject custom accessors / get - objective-c

I have two objects, forms and customers. A job has forms a form can have child forms. What I'd like to do is, because the form relationship is recursive and only the top form has the relationship to the job, in my Form NSManagedObject I'd like to return the topmost 'parentForm.job' if self.job is nil.
import "Form.h"
import "Job.h"
#implementation Form
// Insert code here to add functionality to your managed object subclass
Usually in non managed objects I'd do
-(Job *)job
{
if (!_job && self.parentForm)
return self.parentForm.job;
return _job;
}
But alas no _properties due to being dynamic... Obviously I can't do this
-(Job *)job
{
if (!self.job && self.parentForm)
return self.parentForm.job;
return self.job;
}
How do I create an accessor for dynamic properties in this instance?
Thanks a bunch.

from Avi's comment
-(Job *)job
{
Job *job = [self primitiveValueForKey:#"job"];
if (!job && self.parentForm)
return self.parentForm.job;
return job;
}

Related

Should I rebind models in ReactiveCocoa MVVM?

I have started setting up my view models so they automatically unbind/bind themselves to any model they represent.
I'm relatively new to ReactiveCocoa and want to know if what I'm doing is bad/good practice or if there's a better way to do it.
For example, if I have a view model that represents a movie model, I would set it up like this:
-(void)bind{
[RACObserve(self, movieModel) subscribeNext:^(id x) {
[self unbindMovieModel];
[self bindMovieModel];
}];
}
-(void)unbindMovieModel{}
-(void)bindMovieModel{
self.titleSignal = [RACObserve(self.movieModel, title)
takeUntil:[self rac_signalForSelector:#selector(unbindMovieModel)];
self.averageRatingSignal = [[self.movieModel currAverageRating]
takeUntil:[self rac_signalForSelector:#selector(unbindMovieModel)];
//Setup some more complex signals, etc...
}
Now if at any point I do:
self.movieModel = newModel;
The view model will unbind from the old movieModel and bind itself to newModel.
Is there a better way? Is this not "reactive"? Any feedback would be really appreciated.
You can drastically simplify this case by moving the movieModel from the static to the dynamic part of the RACObserve macro:
RAC(self.titleLabel, text) = RACObserve(self, movieModel.title);
Then, your view will update both when the model instances are exchanged and when a model instance itself changes.
If your view model contains signals itself, you can do something like the following:
RAC(self.ratingLabel, text) = [[RACObserve(self, movieModel) map:^(id viewModel) {
return viewModel.currAverageRating;
}] switchToLatest];

How can one set up persistent collaborating objects in DigitalMicrograph via scripting?

I have come to really appreciate the benefits of using objects to deploy a given application within the DigitalMicrograph environment via the DMS language. The object-oriented approach opens the door to the use of reusable design patterns involving collaborating objects, e.g. Model-View-Controller (MVC). However, objects within DM seem to be highly volatile due to the use of automatic reference counting to manage their life cycles. In order for an MVC trio, or any other set of collaborating objects, to stay alive long enough to be useful, at least one of them must be rooted in a non-volatile object managed by the DM application. So far, the only such objects I have come across within DM are those based on the UIFrame class (i.e. modeless dialogs and UI palettes). For MVC implementations, this works out fine since it makes sense to implement the View as a UIFrame object. It's just a bit unconventional in that the View object becomes the root object that keeps the MVC trio alive and functioning. Normally it is the Controller object that is rooted in the application and manages the Model and View objects. But what about design patterns that do not involve UI? Is there any (acceptable) way to give a set of collaborating objects persistence without rooting them in a UIFrame object? Are there other application-rooted object types that can serve this purpose? I assume setting up a reference cycle would not be an acceptable approach due to the inevitable risk of memory leaks.
The third, and by far the best and cleanest solution is to launch your object as a 'listener' to some event. As you are looking for an object which should stay in scope as long as DigitalMicrograph is open, its possibly best to listen to the application itself. By listening for the "about_to_close" message you also get the ideal handle to properly release all resources before shutdown. The code is the following:
From my 3 answers this is the one I would use. (The others should just illustrate options.)
class MyPermanentObject
{
MyPermanentObject( object self ) { result("created MyPermanentObject :"+self.ScriptObjectGetID()+"\n");}
~MyPermanentObject( object self ) { result("killed MyPermanentObject :"+self.ScriptObjectGetID()+"\n");}
void DeInitialize( object self, number eventFlags, object appObj )
{
OKDialog( "The application is closing now. Deinitialize stuff properly!" );
}
}
{
object listener = Alloc( MyPermanentObject )
ApplicationAddEventListener( listener, "application_about_to_close:DeInitialize" )
}
I can think of various ways to get this persistence, but the one which jumped to mind first was to launch one object into a background thread, like in the example below. The actual background thread can check every so often if the object should still remain, and by sharing the object ID with the outside world, other objects (which don't have to be persistent) can access the "anchored" object.
A word of warning though: If you keep things in memory like this, you have to be careful when closing DigitalMicrograph. If the object hangs on to some items DM wants to destroy, you might see errors or crashes at the end.
// This is the object "anchored". It will remain in memory, because we launch it on a separate thread.
// On this thread, it loops until a variable is set to false (or until SHIFT is pressed)
Class IPersist : Thread
{
number keepme
IPersist( object self ) { result("created IPersist:"+self.ScriptObjectGetID()+"\n");}
~IPersist( object self ) { result("killed IPersist:"+self.ScriptObjectGetID()+"\n\n\n\n");}
void CallFromOutside( object self ) { Result( "\t IPersist can be used!\n" ); }
void StopFromOutside( object self ) { keepme = 0; }
void RunThread( object self )
{
keepme = 1
Result( "\t Called once at start.\n")
While( keepme && !ShiftDown() ) yield()
Result( "\t Finished.\n")
}
}
// Just and example class used to access the 'anchored' object
Class SomethingElse
{
number keepID
SomethingElse( object self ) { result("created SomethingElse:"+self.ScriptObjectGetID()+"\n");}
~SomethingElse( object self ) { result("killed SomethingElse:"+self.ScriptObjectGetID()+"\n");}
void SetKeepID( object self, number id ) { keepID = id; }
void CallOut( object self )
{
result( "SomethingElse object is accessing CallOut...\n" )
object p = GetScriptObjectFromID( keepID )
if ( p.ScriptObjectIsValid() )
{
p.CallFromOutside()
}
}
void CallStop( object self )
{
result( "SomethingElse object is accessing CallOut...\n" )
object p = GetScriptObjectFromID( keepID )
if ( p.ScriptObjectIsValid() )
{
p.StopFromOutside()
}
}
}
// Main script. Create object on separate thread. Then feed it's ID as "weak reference" into the second object.
{
object ob = Alloc(IPersist)
ob.StartThread()
object other = Alloc(SomethingElse)
other.SetKeepID( ob.ScriptObjectGetID() )
other.CallOut()
If ( TwoButtonDialog( "You can either stop IPerstis now, or by pressing SHIFT later.", "Stop now", "later" ) )
other.CallStop()
}
An alternative way would be to have two objects keep references of each other. This is a deadlock-situation one would normally rather avoid, but for the purpose of anchoring it works as well. No object can go out of scope until you release one on purpose.
Again, it is your responsibility to 'release' things when you want a proper shutdown of the system.
The code for the deadlock-situation is rather slim:
class SelfLock
{
object partner
SelfLock( object self ) { result("created SelfLock:"+self.ScriptObjectGetID()+"\n");}
~SelfLock( object self ) { result("killed SelfLock:"+self.ScriptObjectGetID()+"\n");}
void SetPartner(object self, object p) { partner = p; }
void ReleasePartner(object self) { partner = NULL; }
}
{
object p1 = Alloc(SelfLock)
object p2 = Alloc(SelfLock)
p1.SetPartner(p2)
p2.SetPartner(p1)
if ( TwoButtonDialog( "Release partner", "Yes", "No keep locked" ) )
p1.ReleasePartner()
}

objective C what should I do for making these function threadsafe?

Here is the case.
I got a singleton class call DBManager with sqlite3. And insert,delete,select are done via this class.
suppose now ClassA need to insert a record to table a and ClassB need to select a record from table a. So the presudo code is like this.
Class A
[[DBManager getInstance] insertRecord:#"12345"];
Class B
-(void)processData{
Record r = [[DBManager getInstance] getRecord];
// working with record r. after that doing some layout update
[self.lbTitle setText:r.name];
}
cause in my project, there are 4-5 class will access the db. So sometime a Database is locked error is throw and my app crashed.
I know one of the solution is using GCD dispatch_async(CUSTOM_DB_QUEUE,block)
using these block for all the codes related to the db.
But if so, i need to also modify Class B like this. Am I right?
Class B
-(void)processData{
dispatch_async(CUSTOM_DB_QUEUE,{
[[DBManager getInstance] getRecord onRecordGot:^(Record* r) {
// working with record r. after that doing some layout update
dispatch_async(MAIN_QUEUE,{
[self.lbTitle setText:r.name];
)};
}];
)};
}
Is this approach correct?? so i need to change all my code in DBManager to return the result using block coding??
Is there any simple way for queue up the hold DBManager class??
There's a better approach. Do not make any changes to your code that calls DBManager. All changes should be made inside your DBManager class. And there is no reason to use dispatch_async. Use dispatch_sync.
This code stays the same:
Class A
[[DBManager getInstance] insertRecord:#"12345"];
Class B
-(void)processData{
Record r = [[DBManager getInstance] getRecord];
// working with record r. after that doing some layout update
[self.lbTitle setText:r.name];
}
In your insertRecord: method you change it to something like:
- (void)insertRecord:(NSString *)record {
dispatch__barrier_sync(CUSTOM_DB_QUEUE, ^{
// original code to insert record
};
}
And your getRecord method becomes:
- (Record *)getRecord {
__block Record *result = nil;
dispatch_sync(CUSTOM_DB_QUEUE, ^{
// original code that sets result
};
return result;
}
By using dispatch_sync and dispatch_barrier_sync, this code allows for any number of concurrent calls to getRecord but only one call to insertRecord. It also ensures calls to getRecord are blocked while insertRecord: is being run.
To make it thread safe, you can use pthread_mutex_t as a global instance. Lock/unlock this mutex according to its usage
e.g.
pthread_mutex_t *dbLock;
Class A
pthread_mutex_lock(dbLock);
[[DBManager getInstance] insertRecord:#"12345"];
pthread_mutex_unlock(dbLock);
Class B
-(void)processData{
pthread_mutex_lock(dbLock);
Record r = [[DBManager getInstance] getRecord];
// working with record r. after that doing some layout update
[self.lbTitle setText:r.name];
pthread_mutex_unlock(dbLock);
}

Binary Tree in Objective-C

I am learning algorithms and data structures and to train I am trying to design and implement a binary tree using objective-c.
So far I have the following Classes:
main - for testing
Node - node of tree
BinaryTree - for all methods related to the tree
One of the first methods in BinaryTree class I implemented is insertNode:forRoot:.
- (void)insertNodeByRef:(Node **)node forRoot:(Node **)root{
if (head == NULL) {
head = *node;
}
// Case 2 root is null so can assign the value of the node to it
if (root == NULL) {
root = node;
} else {
if (node.data > root.data) { // to the right
[self insertNode:node forRoot:root.right];
} else if (node.data < root.data) { //or to the left
[self insertNode:node forRoot:root.left];
}
}
}
Where the interface of Node class looks like:
#interface Node : NSObject
#property(nonatomic, assign) int data;
#property(nonatomic, strong) Node * right;
#property(nonatomic, strong) Node * left;
#end
My problem is that I don't know how to access the Node class member variables if I am passing Node as a reference. Whenever I try to access the node properties (like data, left or right) I am getting the following error message:
Member reference base type 'Node *__autoreleasing *' is not a structure or union
So my questions is:
how can I access those properties (data, left or right) and use them to store either int data or reference to another Node?
Hope it makes sense. Thanks!
Your code is mixing two common approaches to the task, hence the problem. You are also using an abstract data type (ADT) type approach, rather than an object-oriented one, so there are three approaches to consider.
In both ADT approaches your tree is represented by a reference to its root, in Objective-C this is probably stored in an instance variable:
Node *TreeRoot;
Note also that both of these algorithms use field references, a->b, rather than property references, a.b - this is because the former references a variable and the second algorithm requires passing a reference to a variable.
Functional ADT: Pass-by-value and assign result
In this approach a node is inserted into a tree and a modified tree is returned which is assigned back, e.g. the top-level call to insert a Node nodeToInsert would be:
TreeRoot = insertNode(nodeToInsert, TreeRoot);
and the insertNode function looks like:
Node *insertNode(Node *node, Node *root)
{
if(root == nil)
{ // empty tree - return the insert node
return node;
}
else
{ // non-empty tree, insert into left or right subtree
if(node->data > root->data) // to the right
{
root->right = insertNode(node, root->right);
}
else if(node->data < root->data)//or to the left
{
root->left = insertNode(node, root->left);
}
// tree modified if needed, return the root
return root;
}
}
Note that in this approach in the case of a non-empty (sub)tree the algorithm performs a redundant assignment into a variable - the assigned value is what is already in the variable... Because of this some people prefer:
Procedural ADT: Pass-by-reference
In this approach the variable holding the root of the (sub)tree is passed-by-reference, rather than its value being passed, and is modified by the called procedure as needed. E.g. the top-level call would be:
insertNode(nodeToInsert, &TreeRoot); // & -> pass the variable, not its value
and the insertNode procedure looks like:
void insertNode(Node *node, Node **root)
{
if(*root == nil)
{ // empty tree - insert node
*root = node;
}
else
{ // non-empty tree, insert into left or right subtree
Node *rootNode = *root;
if(node->data > rootNode->data) // to the right
{
insertNode(node, &rootNode->right);
}
else if(node->data < rootNode->data)//or to the left
{
insertNode(node, &root->left);
}
}
}
You can now see that your method is a mixture of the above two approaches. Both are valid, but as you are using Objective-C it might be better to take the third approach:
Object-Oriented ADT
This is a variation of the procedural ADT - rather than pass a variable to a procedure the variable, now called an object, owns a method which updates itself. Doing it this way means you must test for an empty (sub)tree before you make a call to insert a node, while the previous two approaches test in the call. So now we have the method in Node:
- (void) insert:(Node *)node
{
if(node.data > self.data) // using properties, could also use fields ->
{
if(self.right != nil)
[self.right insert:node];
else
self.right = node;
}
else if(node.data < rootNode.data)
{
if(self.left != nil)
[self.left insert:node];
else
self.left = node;
}
}
You also need to change the top level call to do the same test for an empty tree:
if(TreeRoot != nil)
[TreeRoot insert:nodeToInsert];
else
TreeRoot = nodeToInsert;
And a final note - if you are using MRC, rather than ARC or GC, for memory management you'll need to insert the appropriate retain/release calls.
Hope that helps you sort things out.
First of all, don't write your methods to take Node **. It's just confusing.
Second, think about how it should work. Describe to yourself how it should work at a pretty abstract level. Translate that description directly into code, inventing new (not-yet-written!) messages where necessary. If there are steps you don't know how to do yet, just punt those off to new messages you'll write later. I'll walk you through it.
Presumably you want the public API of BinaryTree to include this message:
#interface BinaryTree
- (void)insertValue:(int)value;
So how do you implement insertValue:? Pretend you're the BinaryTree object. What's your high-level description of what you need to do to insert a value? You want to create a new Node. Then you want to insert that new Node into yourself. Translate that description directly into code:
#implementation BinaryTree {
Node *root_; // root node, or nil for an empty tree
}
- (void)insertValue:(int)value {
Node *node = [[Node alloc] initWithData:value];
[self insertNode:node];
}
Now think about how you do the inserting. Well, if you are an empty tree, your root_ is nil and you can just set it to the new node. Otherwise, you can just ask your root node to insert the new node under himself. Translate that description directly into code:
- (void)insertNode:(Node *)node {
if (root_ == nil) {
root_ = node;
} else {
[root_ insertNode:node];
}
}
Now pretend you're a Node. You've been asked to insert a new Node under yourself. How do you do it? You have to compare the new node's value to your value. If the new node's value is less than your value, you want to insert the new node on your left side. Otherwise, you want to insert it on your right side. Translate that description directly into code:
#implementation Node
- (void)insertNode:(Node *)node {
if (node.data < self.data) {
[self insertNodeOnLeftSide:node];
} else {
[self insertNodeOnRightSide:node];
}
}
Now you're still a Node, and you've been asked to insert a new node on your left side. How do you do it? Well, if you don't have a child on your left side yet, just use the new node as your left child. Otherwise, you ask your left child to insert the new node under himself. Translate that description directly into code:
- (void)insertNodeOnLeftSide:(Node *)node {
if (self.left == nil) {
self.left = node;
} else {
[self.left insertNode:node];
}
}
I'll leave the implementation of insertNodeOnRightSide: as an exercise for the reader. ;^)
Your code, in my opinion, has a lot of logic errors. Maybe consider reviewing what a pointer-to-pointer is to insure you're designing the desired effect. Likewise, you need to dereference node/root to access them in normal state. Otherwise, the error is valid, Node** is not type of structure or union.
(Node **)node is a pointer to an object pointer so node.something is invalid because you are a reference to far away from the object.
But (*node).something will work.
Addition for comments :
When you originally call this method : -(void)insertNodeByRef:(Node **)node forRoot:(Node **)root how do you call it?
From the error you've post in your comment it look to me that you are doing :
Node *n = [[Node alloc] init];
[aNode insertNodeByRef:n forRoot:aRoot];
when your method signature state that you need to call it like this :
[aNode insertNodeByRef:&n forRoot:&aRoot];
To pass the address of the pointer to the object.
I'm saying this because your error is now stating that your are sending Node * instead of Node ** which are 2 different thing. (( Incompatible pointer types sending 'Node *' to parameter of type 'Node **' ) I've remove the __autoreleasing between the 2 *, it was obscuring the error message.)
So in other word you are passing a pointer to an object when your method is asking for a pointer TO A pointer to an object.

Overriding a setter method, and getting info out

I have a setter method (setMinimumNumberOfSides) that I want to override after using synthesize. In it, I'm putting in a constraint on the instance variable to make sure the int is within certain bounds.
Later in a custom init method, I'm setting another instance variable (numberOfSides), but I need to make sure minimumNumberOfSides and maximumNumberOfSides was set properly within bounds. I tried changing the return value on the setter to a BOOL, so I could pass back a YES or NO if it succeeded/failed, but that created a conflicting method, I'm guessing because I'm using synthesize and overriding the setter.
How can I get the info out easily to check to see if the setter was called and returned successfully?
-(void)setNumberOfSides:(int)sides
{
if ((sides < maximumNumberOfSides) && (sides > minimumNumberOfSides))
{
numberOfSides = sides;
}
else
NSLog (#"Invalid number of sides: %d is outside the constraints allowed", sides);
}
-(void)setMinimumNumberOfSides:(int)minimum
{
if (minimum > 2)
minimumNumberOfSides = minimum;
}
-(void)setMaximumNumberOfSides:(int)maximum
{
if (maximum <= 12)
maximumNumberOfSides = maximum;
}
-(id)initWithNumberOfSides:(int)sides minimumNumberOfSides:(int)min maximumNumberOfSides:(int)max
{
if (self = [super init])
{
self.minimumNumberOfSides = min;
self.maximumNumberOfSides = max;
self.numberOfSides = sides;
}
return self;
}
You don't have to synthesize numberOfSides if you're planning on implementing the getter and setter. Without #synthesize numberOfSides you can return a BOOL if you choose. You'll need to declare the getter/setter in your interface accordingly.
BTW, another approach would be to use the synthesized getter/setter and add a separate method -(BOOL)isNumberOfSidesValid which performs this check.
In a situation like this, you may be better off using a simple call to assert(), or throwing an exception.
The choice will depend on how you see this class being used. If it will be part of a library, and you expect other developers to frequently supply incorrect values for minimumNumberOfSides or maximumNumberOfSides, you should probably throw a proper exception.
A word of warning, though. If you expect the users of your application to frequently supply incorrect values, then an exception is a bad idea. Exception handling in Objective-C is an expensive operation. If these checks are in place for the sake of the user, you should perform input validation, and report errors to the user in a much more friendly manner.
edit: Here is some quick sample code:
-(void)setMinimumNumberOfSides:(int)minimum
{
if (minimum <= 2)
{
[NSException raise:#"invalid minimumNumberOfSides value"
format:#"value of %d is too low (must be > 2)", minimum];
}
minimumNumberOfSides = minimum;
}
edit: Here is another SO question that goes into detail about exception handling in Objective-C.