When is a NSManagedObject really accessible? - objective-c

I have a problem.
I have an NSObjectController called "mapController" and I want to put some defaults when the object is created. I do this inside the windowControllerDidLoadNib method of my document, as suggested by the docs. But…
if (![mapController content]){ // No map defined yet.
[mapController add: self]; // This should create the instance.
NSLog(#"%#",[mapController content]); // Gives NULL.
I tried:
BOOL ok = [mapController fetchWithRequest:nil merge:NO error:nil];
NSLog(#"%#",[mapController content]); // Gives NULL.
The content of mapController is in the Core Data "scratch pad" but I can't access it. I have to set one of its attributes like this:
[[mapController content] setValue:[matrix colorReference] forKey:#"mapData"];
This gives no error, the file is marked as changed, but it I test the value:
NSLog(#"%#",[mapController content]); // Gives NULL.
When the heck it the controller's content really HERE? Something appears on the screen but… what actually? Reading the docs doesn't help me…

OK, I found the answer in the docs:
add: Creates a new object and sets it as the receiver’s content object.
Discussion
Creates a new object of the appropriate entity (specified by
entityName) or class (specified by objectClass)—see newObject—and sets
it as the receiver’s content object using addObject:.
Special Considerations
Beginning with Mac OS X v10.4 the result of this method is deferred
until the next iteration of the runloop so that the error presentation
mechanism can provide feedback as a sheet.
That's why
[[mapController content] setValue:[matrix colorReference] forKey:#"mapData"];
worked fine when called elsewhere in the app. It was a few iterations later…
Well… maybe this post will save you a couple of hours you could use to sleep longer.
Regards,
Bernard

I don't think its your mapController, I think it is your NSLog. Try this:
NSLog(#"%#", mapController);
also try getting simple data from the content, like the float value of the CGColorRef so you can use other formatters like %f.
I would have tested this but I cannot seem to create an instance of NSObjectController because it is an undeclared identifier. What framework is it defined in? Did you have to #import anything?

Related

EXC_BAD_ACCESS when accessing objective-c property

I am bridging an objective-c library to React. In order to return the data I need, I have to use a callback. The only problem is, the native method that kicks off the process that generates the data (which is the method that I call from my React js file), is NOT the method that returns the data. In fact, there are quite a few methods between the one that I call, and the final result.
So I have a few options. Either completely rewrite the entire objective-c program (f*ck that), pass the callback function as an argument to every single method and ultimately to the final method where it will be used (this 'works' but is ugly), or a third option which this post is about.
I am new to objective-c (very new) so go easy on me.
Instead of passing the callback function around to every single method, I want to try and make it 'global'. My attempt at doing this looks like
#property(nonatomic,copy)RCTResponseSenderBlock globalCallback;
and the method where it is 'initialized' (which is also the method I call from js)
RCT_EXPORT_METHOD(startScan:(RCTResponseSenderBlock)callback) {
self.globalCallback = callback;
...
}
Now just to test that this works, I added a line of code immediately below the line where I 'initialized' my globalCallback:
RCT_EXPORT_METHOD(startScan:(RCTResponseSenderBlock)callback) {
self.globalCallback = callback;
self.globalCallback(#[[NSNull null], #"Test string"]);
...
}
And it works (as far as I can tell). The callback returns "Test String" to React, and I am able to see it. So I went over to the method where I actually want to return information from and added the same line of code to it (obviously removing the one from the above example):
-(void)theMethodIWantToReturnFrom {
self.globalCallback(#[[NSNull null], #"Test string"]);
...
}
However, this time it does not work. I get EXC_BAD_ACCESS. From what I understand, this may mean that my globalCallback has been deallocated. But whatever it means, I have not been able to figure out a solution yet. Any ideas / explainations regarding this error?

ARC deallocate my NSmutablearray before NSTableview reloaddata

My NSMutableArray lOfSegments, declared as IVAR, get populated correctly. During the debug it shows 4 object in the array.
for (int x=0; [arrayOfSegmentsTcIn count]>x; x++) {
NSDictionary *segmentDic=[[NSDictionary alloc] initWithObjectsAndKeys: [arrayOfSegmentsNumbers objectAtIndex:x],#"segment",[arrayOfSegmentsTcIn objectAtIndex:x],#"tc_in",[arrayOfSegmentsTcOut objectAtIndex:x],#"tc_out", nil];
[lOfSegments addObject:segmentDic];
[myDMXML.segments addObject:segmentDic];
}
[self.xmlTCLable setStringValue:[myDMXML startTimeCode]];
[self.xmlDurationLable setStringValue:[myDMXML duration]];
[self xmlValidationCheck];
NSLog(#"arrayController:%#",[lOfSegments valueForKey:#"segment"]);
[self.tableViewOutlet reloadData];
NSLog list the array correctly but when reloadData is executed the code jumps to
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView {
return [lOfSegments count];
}
The array is null.
The Object is initialised in viewDidLoad as
lOfSegments = [[NSMutableArray alloc]init];
Please Help!
First, I recommend making your code more clear here by using self.lOfSegments rather than directly accessing an ivar. (The fact that the ivar lacks a leading _ is very suspicious as well, and raises the question of whether this is even the variable you think it is.)
On the assumption that this is the variable you think it is, and that you have overridden the standard behavior to make the ivar match the property or created explicit ivars (neither of which you should do), there are several common causes for this kind of problem:
The most likely cause is that you called your initialization code prior to viewDidLoad and then viewDidLoad blew away the array. Many things can run prior to viewDidLoad, and viewDidLoad can run more than once (at least this used to be true; I'd have to study whether the view-loading changes in iOS 6 made it guaranteed to be run once.)
You have some other way reset lOfSegments between the time your initialization code ran and the time reloadData ran. If you would reliably use self. then you could override setLOfSegments: so you could log this. Or you could mark this property readonly so you could prevent it. Thats one of many reasons that you should use properties, not ivars.
The setting code failed to run before reloadData. Ensure that the log statement actually printed prior to getting to reloadData and is on the same queue (the queue identifier will be part of the NSLog output in brackets). I don't think this is likely given your description, but it is a common problem.
There are two instances of this object. Make sure that the object that ran your initialization code is the same object that ran reloadData. This is a more common mistake then you may think. Log self and make sure the memory address is the same in both cases.
looks like you have variable with same name lOfSegments in method viewDidLoad. So in viewDidLoad you use stack variable, in numberOfRowsInTableView - instance variable.
Or maybe tableViewOutlete.dataSource pointing on different viewController

makeObjectsPerformSelector not working on IOS7.1

i have array of buttons (IBOutletCollections) name "topFriends"..i need to set hidden the all buttons of topFriends(array name).
[self.topInFriends makeObjectsPerformSelector:#selector(setHidden:) withObject:[NSNumber numberWithBool:YES]];
Actually its working on iOS7...but its not working on iOS 7.1 .
but when i try to enumerate the array like following,then its working for iOS7 and 7.1
[self.topInFriends enumerateObjectsUsingBlock:^(UIButton * obj, NSUInteger idx, BOOL *stop) {
obj.hidden=YES;
}];
Can anyone please tell me why makeObjectsPerformSelector function not working in iOS 7.1 .I am really frustrated to find the issue..please anyone help me..thanks in advance
I got this from the docs of makeObjectsPerformSelector and this is the description of the parameter SEL in this method
A selector that identifies the message to send to the objects in the array. The method must take a single argument of type id, and must not have the side effect of modifying the receiving array.
Then I run this line
[self.topInFriends makeObjectsPerformSelector:#selector(setHidden:)
withObject:#"Fcuked up"];
It hides the button, So it doesn't matter what you are passing. And it makes sense too as your method expect a BOOL and you are giving an object to it, I don't know the exact internal implementation of makeObjectsPerformSelector but I can conclude some points
When you pass some object say #"abc" or #YES and when makeObjectsPerformSelector invokes your setHidden then it's passing object, which obviously has some address too, to setHidden and it converts your object(address) into BOOL.
Suppose your addresses are
#"Fcuked up" ---> 0x7cde450034798976 (assuming 64 bit pointer)
#YES ---> 0x7cde450000000000
For first case the value of BOOL will become true as it's LSB are non-zero and for second case the BOOL will become false as LSB are zeros.
In whole you should respect apple docs and you should not call a method which doesn't take parameter as id
All thoughts appearing in this answer are mine. Any resemblance to other persons, living or dead, is purely coincidental.
Use [self.topInFriends setValue:#YES forKey:#"hidden"]; instead.

What is the need for a primitive when using a transient property?

What is it?
I'm not sure I quite understand what this does.
- (NSString *)sectionIdentifier {
[self willAccessValueForKey:#"sectionIdentifier"];
NSString *tmp = [self primitiveSectionIdentifier];
[self didAccessValueForKey:#"sectionIdentifier"];
if (!tmp) {
tmp = #"bananas";
[self setPrimitiveSectionIdentifier:tmp];
}
return tmp;
}
How come I need this primitiveSectionIdentifier?
Ultimately, I'm using a example project from Apple's documentation to create a section identifier, to use with my NSFetchedResultsController.
While this does work. I am saying to myself that,
"sectionIdentifier" will be accessed,
then I'm setting "tmp" to primitiveSectionIdentifier. But primitiveSectionIdentifier has nothing there at this point!! Does it?
I then say I did access "sectionIdentifier". But I can't see how that happened between "Will" and "Did"!
Can someone help me understand this?
[self primitiveSectionIdentifier] is a so-called "primitive accessor" (see the Glossary of the Core Data Programming Guide). That is the function that actually fetches the value of the "sectionIdentifier" from the persistent store. The function is automatically created by the Core Data runtime.
willAccessValueForKey and didAccessValueForKey are "notification methods". According to the documentation, they are used for key-value observing, maintaining inverse relationships and so on.
So the pattern is:
Tell everybody that you are going to read a value.
Read the value.
Tell everybody that you have read the value.

How do I keep an NSPathControl updated with the path of the selected cell in an NSBrowser

I need to keep an NSPathControl updated with the currently selected path in an NSBrowser, but I'm having trouble figuring out a way of getting notifications when the path has changed from the NSBrowser. The ideal way to do this would just to be to observe the path key path in the NSBrowser, but that gives a KVO can only observe set<key> methods which return void message and no updates (setPath returns a bool success value).
I also tried observing the selectedCell key path, but I'm not getting notifications when the selection there is changed.
Is there some other really obvious way to do this that I'm missing?
Courtesy of Rob Keniger over at Cocoa Dev:
Have you looked at the SimpleBrowser
example in /Developer/Examples? It
shows how to get the current selection
when it is changed by the user,
basically by just setting up the
action of the NSBrowser.
That is indeed the way to do it. Just implement a method like - (void)browserClicked: in your controller and map it to the NSBrowser's action in interface builder with whatever you want to happen each time the selection changes inside that method, e.g.
- (void)browserClicked:(id)browser {
self.pathToSelectedCell = [browser path]; // NSPathControl is bound to pathToSelectedCell
}
I just checked in IB, and it looks like NSBrowser has a selection index paths binding (an array of NSIndexPath objects) that you could possibly monitor with KVO. It's strange but I don't see any mention of it in the docs, so you might need to do a little research to see if that's something you should or shouldn't use, even if it seems to work. If it does, in your KVO observation method you would find the browser's current path, and convert that to an NSURL the path control can use.
If that doesn't work there's also the delegate methods - (BOOL)browser:(NSBrowser *)sender selectRow:(NSInteger)row inColumn:(NSInteger)column and - (BOOL)browser:(NSBrowser *)sender selectCellWithString:(NSString *)title inColumn:(NSInteger)column.
As of 10.6, one can find out which items are selected, by using the delegate callback as follows:
- (NSIndexSet *)browser:(NSBrowser *)browser selectionIndexesForProposedSelection:(NSIndexSet *)proposedSelectionIndexes inColumn:(NSInteger)column
{
NSLog(#"New first item of the new selection is at index %#", [proposedSelectionIndexes firstIndex]);
// Do something with the selected index or indicies
return proposedSelectionIndexes; // Allow the selection to occur by not changing this
}