awakeFromInsert called twice with nested contexts - objective-c

This project uses Mogenerator and Magical Record. I have tracked down a bug to the fact that awakeFromInsert is getting called twice. Once for each of my contexts I presume. This is an issue because I need to listen for NSNotifications on this NSManagedObject like this:
- (void)awakeFromInsert
{
// Listen for a return from background mode
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(enteringForeground:) name:UIApplicationWillEnterForegroundNotification object:nil];
}
But awakeFromInsert get's called twice which is rather annoying. I want to call a method ONCE when my NSManagedObject is first created.
After searching this solution seems to make a lot of sense. However I can't see how I can add a category onto NSManagedObject when using Mogenerator and MagicalRecord. Without some complex overriding.
In MagicalRecord MR_createEntity calls
if ([self respondsToSelector:#selector(insertInManagedObjectContext:)])
{
id entity = [self performSelector:#selector(insertInManagedObjectContext:) withObject:context];
return entity;
}
Is there a neater solution to this issue?

Ok well this feels very hacky but appears to work. I created the following class methods on my human readable NSManagedObject class:
+ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_ {
JWBoard *newobject = [super insertInManagedObjectContext:moc_];
[JWBoard awakeFromCreate:newobject];
return newobject;
}
+ (void)awakeFromCreate:(JWBoard *)board
{
// do setup stuff & add observers
}
Open to much better solutions!

Open to much better solutions!
I wish! Would have been easy enough for apple to not invoke awakeFromInsert, or to at least provide a flag that's true in the context of a "parentProcessSaveRequest." If you look at the call stack for the not-first calls to awakeFromInsert, the stack always contains parentProcessSaveRequest.
Here's some terrible code proving as much:
- (void) awakeFromInsert
{
[super awakeFromInsert];
NSArray* stackArray = [NSThread callStackSymbols];
for (NSString* method in stackArray)
{
if ([method rangeOfString:#"_parentProcessSaveRequest"].location != NSNotFound)
{
NSLog(#"Parent insert %#",self.objectID);
return;
}
}
NSLog(#"First insert %#",self.objectID);
// Initialize here
}
And the log output -- the objectId stays the same:
2014-05-19 20:53:52.964 myApp[1891:a01f] First insert 0x6000000326c0 <x-coredata:///MyEntity/t496E9B17-E170-4A7C-B7D4-7D8B92433E1C2>
2014-05-19 20:53:53.531 myApp[1891:303] Parent insert 0xdca8000eb <x-coredata://7274869F-4BF3-4B8A-9270-A64E54476AAD/MyEntity/p14122>
2014-05-19 20:53:53.537 myApp[1891:303] Parent insert 0xdca8000eb <x-coredata://7274869F-4BF3-4B8A-9270-A64E54476AAD/MyEntity/p14122>
Seems to work for saving to any of the nested contexts that I have, ugly as it is.
Unfortunately I cant figure any reasonable way to determine whether awakeFromInsert is being called in the context of a parentProcessSaveRequest. Come on, Apple! Give us a flag here.

here is the simplest one:
when parentContext is null, means when this context is saved you can do you custom logic, for example incrementing table number
- (void)awakeFromInsert
{
if (!self.managedObjectContext.parentContext) {
//setting tableNumber
[self willChangeValueForKey:#"number"];
[self setPrimitiveNumber:tableNumber];
[self didChangeValueForKey:#"number"];
}
}

Related

Why is locationManager:didUpdateHeading: not able to update this global?

I want to store the continuously updated values returned by the locationManager:didUpdateHeading: method in either a global int or a property int, so that other functions of the MotionHandler class can use it. However, this delegate method doesn't seem to be able to store its values globally but only locally. Why is that? Is it because it's not an actual MotionHandler method? How can I work around this problem? Thank you for your help.
MotionHandler.m
#import "MotionHandler.h"
#interface MotionHandler()
{
CLLocationManager *locationManager;
int degrees; // the global in question..
}
#end
#implementation MotionHandler
-(void) startCompassUpdates
{
locationManager =[[CLLocationManager alloc] init];
locationManager.delegate=self;
[locationManager startUpdatingHeading];
}
-(void)locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading
{
// This is working, a new value is stored in "degrees" & logged on the console after each update. However it only seems to be updating "degrees" locally..
degrees = (int)locationManager.heading.magneticHeading;
NSLog(#"from delegate method: %i", degrees);
}
-(int) showDegrees
{
return degrees; // This is not working. Whenever I call this method, "degrees" is always zero. Why isn't this global being updated by the previous method ?
}
TheViewController.m
//...
- (void)viewDidLoad
{
[super viewDidLoad];
currentMotionHandler = [[MotionHandler alloc] init];
[currentMotionHandler startCompassUpdates];
while(1==1)
{
NSLog(#"from showDegrees method: %i",[currentMotionHandler showDegrees]); // this just keeps returning zero..
}
}
//...
As per OP request, I have transferred my comments to an answer:
You need to stop using while loop to get constant feedback of the changing value. As Cocoa Touch is an event-based system you can't hijack its run loop by creating an infinite loop in this way. Even outside of an event-based system, using such a tight loop would hurt performance and give little gain.
If you want continuous update (or something that appears to be continuous) you can:
Use a timer to call a method every X milliseconds (see Apple Guide).
Use a background thread (see Apple Guide).
I would prefer to use the timer approach as that has the lowest overhead and runs the method in the same thread as the rest of the UI, avoiding any possible threading issue.

How to implement atomic properties in objective C (with or without ARC)?

This is how I implement mine. Sometihng just doesn't fill right
-(void)setCurrentAnchor:(CLLocation *)currentAnchor
{
//CM(#"set current anchor");
/*#synchronized (self)
{
}*/
if (_currentAnchor==currentAnchor)
{
return;
}
//[Tools DoSomethingWithSynchronize:^{
#synchronized(self){
_currentAnchor=currentAnchor;
[Timer searchCriteriaChanged];
[cachedProperties setDistanceForAllBiz];
}
//}];
}
-(CLLocation *)currentAnchor
{
//[Tools DoSomethingWithSynchronize:^{
//}];
#synchronized(self){
} //Empty #synchronized section just to block every other thread
[self setCurrentLocationasAnchorifNil];
return _currentAnchor;
}
The objective is of course to ensure that currentAnchor is never accessed when it's changing. Am I doing this right?
You are far better off using dead simple getter/setter implementations -- #synthesize ideally -- and move all change-response logic outside of the getter/setter. KVO works fine if you need single getter/setter response logic. You'll have to have an external transaction mechanism if you want to batch up a response to multiple property changes.

Self destructing singleton design pattern iOS

I recently came across an issue in which I only wanted one instance of a particular object to exist, and exist for only the brief period of time it needed to perform a specific operation. Its operation was asynchronous so ARC would dealloc it at the end of the run loop if I didn't hold a reference to it. If I did hang onto it I would need delegate callbacks or notifications to know when it was done to release it.
The object needed to download several images and other data and cache it to disk. I didn't want it to waste memory when it wasn't caching items since the cache limit was around 24 hours. I also didn't need feedback of any kind from it; I wanted it to perform it's task and be done with itself.
I came up with a design pattern I liked quite nicely. I've used it in a few other projects since then, and was curios if it was a well known and analyzed pattern that I'm just not aware of (self-destructing singleton???). I'd like to know so I can be made aware of any potential pitfalls I'm not currently seeing.
I'm also very interested to hear any input you guys might have about why this is a bad design.
The Design Goes Like This (this is ARC, but non-arc can work too if you release the singleton through a class method):
A global static object (not really a singleton because it doesn't live the entire time)
static MySelfDestructingClass* singleton;
A single public class method
+ (void)downloadAndCacheDataIfNeeded
{
//Force synchronized access
#synchronized(singleton){
//We are already doing something, return
if(singleton){
return;
}
NSDate* lastCacheDate = [[NSUserDefaults standardDefaults] objectForKey:kKeyForLastUpdate];
if([[NSDate date] timeIntervalSinceDate:lastCacheDate] > kCacheLimit){
//Our cache is out of date, we need to update
singleton = [[self alloc] init];
[singleton downloadAndCache];
}
}
}
Now our instance methods, we need our object alive so the request can come back:
- (void)downloadAndCache
{
//This would probably be a delegate, but for simplicity of this example it's a notification
[[NSNotificationCenter defaultCenter] addObserver:self forNotificationWithName:NotificationSomeRequestDidSucceed selector:#selector(someCustomRequestDidSucceed:withData:) object:nil];
[SomeCustomRequest makeRequestWithURL:#"http://www.someURL.com"];
}
- (void)someCustomRequestDidSucceed:(SomeCustomRequest *)request withData:(NSDictionary *)dictionary
{
//Do whatever we need to in order to save our data, or fire off image download requests etc...
....
//Set our lastUpdated time in NSUserDefaults
[[NSUserDefaults standardDefaults] setObject:[NSDate date] forKey:kKeyForLastUpdate];
//Remove our observer
[NSNotificationCenter defaultCenter] removeObserver:self name:NotificationSomeRequestDidSucceed object:nil];
//Release ourselves (ok not really, but tell arc we can be released)
singleton = nil;
}
This way all I have to do anywhere else in the application is:
[MySelfDestructingClass downloadAndCacheDataIfNeeded];
Now this object will download things if it needs to and release itself when it's done, or not create itself at all. It also won't go and start downloading the data twice.
I'm aware this design has limitations with extendibility and functionality, but for an instance like this, and the other ones I've used it for, I've found it quite useful.
This pretty common using blocks. Consider something similar (though I would probably handle multiple invocations differently...)
void ExecuteWithMySingleSelfDestructingObject(void(^block)(MySelfDestructingClass *object)) {
static MySelfDestructingClass* singleton;
#synchronized(singleton) {
if (singleton) {
// To get past the synchronization primitive, this must be a recursive call.
}
// Whatever other conditions you want to have (like your date check)
singleton = [[MySelfDestructingClass] alloc] init];
#try { block(singleton); }
#finally { singleton = nil; }
}
}
Note double exception handling (try/finally plus what #synchronized does - may want to change that...
Then do whatever you want with the block...
ExecuteWithMySingleSelfDestructingObject(^(MySelfDestructingClass *object){
// Do whatever I want with the singleton instance that has
// been given to me as <object>
});
Of course, it could be a class method...
+ (void)performBlock:(void(^)(MySelfDestructingClass *object))block {
static MySelfDestructingClass* singleton;
#synchronized(singleton) {
if (singleton) {
// To get past the synchronization primitive, this must be a recursive call.
}
// Whatever other conditions you want to have (like your date check)
singleton = [[self] alloc] init];
#try { block(singleton); }
#finally { singleton = nil; }
}
}
[MySelfDestructingClass performBlock:^(MySelfDestructingClass *object){
// Do whatever I want with the singleton instance that has
// been given to me as <object>
}];
I hope that makes sense (I typed it free-hand, so syntax may vary, but you should get the idea).

Reusing NSObjects by Overriding release in Obj-C

I am implementing an object reuse scheme using a singleton class.
What I do basically is:
MyClass* obj = [[MyClassBank sharedBank] getReusableItem];
The bank is just an NSMutableSet tweaked for optimum reusability. When I was happily implementing this Singleton, I had in mind that I will just do the following when I am done with "obj":
[[MyClassBank sharedBank] doneWithItem:obj];
Currently, My code would work if I where to use it this way, but I later realized that I sometimes add "obj" to an "NSCollection", and sometimes I call:
[theCollection removeAllObjects];
At first I thought about making my own class that is composed of a collection, then I would iterate the objects within the collection and call:
[[MyClassBank sharedBank] doneWithItem:obj];
But, that's too much of a hassle, isn't?
A neat idea (I think) popped into my mind, which is to override: -(oneway void)release;, so, I immediately jumped to Apple's documentation, but got stuck with the following:
You would only implement this method to define your own reference-counting scheme. Such implementations should not invoke the inherited method; that is, they should not include a release message to super.
Ao, I was reluctant to do that idea .. basically:
-(oneway void)release{
if ([self retainCount] == 1) {
//This will increment retain count by adding self to the collection.
[[MyClassBank sharedBank] doneWithItem:self];
}
[super release];
}
Is it safe to do that?
PS: Sorry for the long post, I want the whole idea to be clear..
EDIT:
How about overriding alloc alltogther and adding [[MyClassBank sharedBank] getReusableItem]; there?
Suggested method:
You're playing with the reference counting system. 99.9999999999999999% of the time this is a bad idea. I would highly recommend going with a different mechanism. Perhaps these objects could implement their own reference count that's independent of the retainCount? Then you could use that referenceCount to actually control when an object is ready to be re-used or not.
Not suggested method:
If, for some weird reason, you can't do that, then you could do the following thing that is still a bad idea and that i don't recommend you actually use:
You can override dealloc:
- (void)dealloc {
[ivar release], ivar = nil;
[anotherIvar release], anotherIvar = nil;
somePrimitive = 0;
// do not call [super dealloc]
}
- (void)_reallyDealloc {
[self dealloc]; // clean up any ivars declared at this level
[super dealloc]; // then continue on up the chain
}
Basically, the dealloc method would be the point at which the object is ready for re-use. When you're totally done with the object and finally want it to go away, you can use the _reallyDealloc method to continue on up the chain, eventually resulting in the object getting freed.
PLEASE don't do this. With things like Automatic Reference Counting, this is going to introduce you into a world of hurt and really bizarre debugging scenarios. A lot of the tools and classes and stuff depend on the reference counting mechanism to be working without alteration, so screwing around with it is usually not a Good Idea™.
For ppl who find this approach interesting/useful, Here is a cleaner way than calling [super dealloc]; directly (which is definitely bad)
//BAD!
//-(void)dealloc{
// for some reason, the retainCount at this point == 1
// if (![[BankStep sharedBank] purgeFlag]) {
// [self resetObject];
// [[BankStep sharedBank] doneWithItem:self];
// } else {
// [children release];
// [super dealloc];
// }
//}
by calling [[Bank sharedBank] purgeBank]; , set the flag to true, then remove all objects from the NSSet.
Adapted solution:
#Joe Osborn idea of using categories to implement a returnToBank Method!

Should I include the managed object context as a parameter to a method?

Problem
I'm including the managed object context as a parameter of a method when I work with Core Data.
Although this makes the code easier to test, it's messy.
Questions
Is this good or bad practice?
Is there a neater, easier way of doing this that keeps methods testable?
Background
The example below is a background operation that has it's own context.
Any advice from more experienced coders would be much appreciated!
Code
#interface JGTrainingGroupCleanupOperation : JGCoreDataOperation {
NSManagedObjectContext *imoc;
}
...
#implementation JGTrainingGroupCleanupOperation
-(void)main {
[self startOperation]; // Setting up the local context etc
[self cleanupTrainingGroupsInMOC:imoc];
[self finishOperation];
}
-(void)cleanupTrainingGroupsInMOC:(NSManagedObjectContext *)moc {
NSSet *trainedGroups = [self fetchAllTrainedGroupsInMOC:moc];
[self deleteDescendantsOfGroups:trainedGroups fromMOC:moc];
[self removeStubAncestorsOfGroups:trainedGroups fromMOC:moc];
}
-(NSSet *)fetchAllTrainedGroupsInMOC:(NSManagedObjectContext *)moc_ {
return [moc_ fetchObjectsForEntityName:kTrainingGroup withPredicate:[NSPredicate predicateWithFormat:#"projectEditedAtTopLevel == nil"]];
}
-(void)deleteDescendantsOfGroups:(NSSet *)trainedGroups fromMOC:(NSManagedObjectContext *)moc_ {
// More code here
}
-(void)deleteDescendantsOfGroup:(JGTrainingGroup *)trainedGroup fromMOC:(NSManagedObjectContext *)moc_ {
// More code here
}
In my (not so humble) opinion I'd say it's mostly a matter of style. You can do it this way or you can #synthesize the moc and call [self moc] or self.moc.
Me? I'd go the accessor route personally, mostly because class members shouldn't have to be told where to find an object dereferenced by an iVar anyway. If you're accessing something that's an iVar within the same class, I'd use the iVar directly or an accessor.
I believe the difference in performance would be negligible, so I wouldn't really bother much on that front (even though you didn't ask).