Xcode Updating a table from another method - xcode

I have a code_tab.m file which deals with the UI and code.m file which does the crunching of data and also updates a MutableArray. When the code.m updates the array I want to update the table in view linked to the connection_tab.m. I have a function in code_tab.m that has a:
[self.table tableupdate]
Which works as expected when called internally. When the same function is called from the code.m file (when the array has been updated) nothing happens even though I can see the same code is being accessed.
I have setup access by having this line in the code.h file:
connection_tab* connectiontab_script;
and then calling it in code.m with
connectiontab_script = [[connection_tab alloc] init];
[connectiontab_script tableupdate];
I've obviously missed something vital. Is there a way that one method can alter the visual display of another, in this case update the table already on screen?

Technically you should avoid having your data class make calls to methods in your view as it will likely cause you headaches in future, MVC is the recommended development practice.
However, you could achieve what you're trying to do by amending your initNetworkCommunication method in code to pass a reference to the active view through:
- (void) initNetworkCommunicationForView:(UIViewController*)passedVC
Which you'd call from inside connection_tab like:
[appDelegate.connection_script initNetworkCommunicationForView:self];
Then in code you'd do (if statement avoids warnings):
if ([passedVC respondsToSelector:#selector(tableupdate)]) {
[passedVC performSelector:#selector(tableupdate)];
}
Depending on the structure of your code class you may need to create a class-wide variable to store passedVC in if the tableupdate call isn't within initNetworkCommunication.
P.S You could also customize the method to be specific to your connection_tab class like:
- (void) initNetworkCommunicationForView:(connection_tab*)passedCT
Then you could ditch the selector stuff and go with:
[passedCT tableupdate];
But I went with UIViewController for compatibility reasons.

Related

Extra Incorrect KVO Insertion Called on NSOrderedSet When Saving Child NSManagedObjectContext

I have an NSManagedObject with an NSOrderedSet to-many relationship named subpointConnections_. I am observing changes to this set using the following:
addObserver(self, forKeyPath: #keyPath(subpointConnections_), options: [], context: &subpointsOC)
This can be called only once in the initialisation of a lazy property on the NSManagedObject.
Any new relations are added in a child NSManagedObjectContext, and then saved down to my main context.
When I set the relationship, I use the following code, only setting the 'many' side of the relationship from the 'one':
superpoint.insertIntoSubpointConnections_(self, at: index)
insertIntoSubpointConnections_ is an autogenerated accessor.
In the child NSManagedObjectContext I see a single correct call to observeValue(forKeyPath..., that gives me the correct insertion index on subpointConnections_, when the above insertion code is called.
However, when I save to the parent NSManagedObjectContext I am seeing two calls to observeValue(forKeyPath... on the same object. The first call is for an insertion at the end of the NSOrderedSet. The second call is for an insertion at the correct position.
When evaluating the NSOrderedSet in each observation call, the new object is indeed at the position described - it is on the end of the set on the first call, and then moved to the correct position on the second call. However, I get no call to say that it was removed from the end position.
I am not sure if I have set something up incorrectly here. The many objects in my one-many relationship will be unique, so I could write the code to work around this, but that feels wrong.
Any thoughts on what I might be doing wrong?
Weirdly, the first change dictionary passed to observeValue(forKeyPath... contains an NSIndexSet, the second contains an NSMutableIndexSet.
EDIT
I have replicated this issue in a simple project here: https://github.com/GilesHammond/KVO-Core-Data-Extra/
Run in debug and select "ADD CHILD" multiple times from the app Main Menu. Observe the debug output showing the extra erroneous observation on the main NSManagedObjectContext.
I contacted Apple Support and have submitted this issue as a bug as suggested, as the given notifications are not atomic.
I had to take a different approach. I now update my NSManageObject when the NSManagedObjectContextDidSave notification is posted.

Detect attempt to insert nil on a dictionary and log a backtrace

Is there a way I can detect an attempt to insert a nil value on a dictionary and log a backtrace on my application ?. I know how to do it with Xcode, but the error occurs only with some users. Hence I need to send them a new build that hopefully would log a backtrace of the attempted nil insertion.
This is probably because an image or a font is not being loaded correctly, if there is another way to find out I would also like to know.
You can't do this with regular NSMutableDictionary objects, as adding a nil value is legal.A workaround would be to use a custom dictionary implementation that wraps a NSDictionary instance and forwards all methods to the wrapped objects; and in the case of setObject:forKey: (or setValue:forKey:) makes a check and logs the backtrace if the value is nil. The downside is that you'll have a lot of boiler plate code to write. You can reduce the boiler plate code size if you implement only the methods needed by your code.
Another approach would be to use method swizzling and replace the setObject:forKey: and setValue:forKey: with your method that firstly checks the value and if OK forwards the call to the original method. However NSDictionary being a class cluster you might experience problems with this approach.
Update. Just thought of a 3rd solution: add a category over NSMutableDictionary with getters/setters for the keys you're interested in, and update your code to call those setters instead of the setObject:forKey: method.
As I understand your problem you have failed to check the result when loading an image, font or something similar and this is causing an error when the bad result is later inserted into a dictionary. What you are after is a quick way, as you have a large codebase, to track down that insertion so you can backtrack and find the source of the problem and add appropriate checking code to the load/whatever.
What you can do is:
Replace NSMutableDictionary with a simple class, say DebuggingDictionary, which appears to be (explained below) a derived class and just checks for nil on insertion and produces the diagnostics you are after; and
Do a find/replace over your code base for [NSMutableDictionary alloc] and replace with [DebuggingDictionary alloc]. You can easily change this back once the problem has been fixed.
So how to write DebuggingDictionary?
Well as NSMutableDictionary is a class cluster you cannot just derive from it and override setObject:forKey:, you have provide your own storage for the keys & objects and override six key methods and all (or at least all you use) of the init methods.
Sounds bad but it isn't. First read this answer to a different but related question. In that answer a version of NSMutableArray is created which checks the type of elements added, you need to check whether the items are nil. The implementation provides the storage by wrapping a real NSMutableArray. You can do the equivalent with NSMutableDictionary, the documentation (NSMutableDictionary and NSDictionary) lists the six primitive methods you need to override.
That answer also adds its own initWithClass: initialisers and blocks the standard ones, you just need to implement the standard dictionary ones - by calling them on the wrapped dictionary.
[Minimal checking in the following code sketches, all typed directly into answer so beware of typos]
So for example initWithCapacity: becomes something like:
- (instancetype) initWithCapacity:(NSUInteger)numItems
{
realDictionary = [NSMutableDictionary dictionaryWithCapacity:numItems];
return self;
}
and the core insertion method becomes:
- (void)setObject:(id)anObject forKey:(id<NSCopying>)aKey
{
if (anObject == nil)
{
// produce your diagnostics
}
else
realDictionary[aKey] = anObject;
}
Once you've tracked your problem to its source and fixed it there just remove your DebuggingDictionary and find/replace all occurrences in your code with NSMutableDicitionary.
HTH
You could create subclass of NSAplication and override method reportException
Use
+[NSThread callStackSymbols];
or
-[NSException callStackSymbols];
to get a backtrace. You can print a backtrace using NSLog.
You may find also Apple's example useful for you:
ExceptionReporting:
Demonstrates how to show a customized exception reporting user interface.
This lets the user know when the exception happens in order to possibly prevent
subsequent random crashes that are difficult to debug.
Instead of setting key/value directly to the dictionary, how about using a method that accepts parameters that should be inserted into the dictionary and tests each for nil before adding it to the dict?
-(void)addKeyAndValueToDict:(NSString*)aKey andValue:(NSString *)aValue {
if ( aValue == nil ) {
NSLog(#"value was nil for key: %#", aKey);
return;
}
[self.someDict setValue:aValue forKey:aKey];
}

what does "failed to load window nib file" mean?

I'm working on my first Cocoa application, and I'm hoping very much that
[NSWindowController loadWindow]: failed to load window nib file 'Genius Document'
means that there's something very specific I've done wrong, because if I have to go back and redo all the bindings I'll want to kill myself.
FWIW, I'm working with a document-based application that has (so far) only one XIB file and no NIB files.
I can post code/screenshots of my bindings but in case that's not necessary I didn't want to make people wade through them.
Thanks for the help.
The error you have described ultimately occurs because a call to load the nib file is failing. Make sure you've supplied the correct name for your Interface Builder file.
You can supply the correct value in a number of ways (depending on your use of AppKit), so I'll lay out the two most common possibilities and you can track down which one applies to you. Given what you've said in your question, I suspect you'll be dealing with the first scenario.
NSDocument windowNibName
If you are relying on the document architecture's defaults, you are probably not making the call in question directly. Instead, the framework makes the call on your behalf, using whatever nib name you specify on the given document class.
For example, if you were to make a new document-based project with a document class of "XYZDocument," the Xcode template would provide you with a basic XYZDocument class and a XYZDocument.xib file. The XYZDocument implementation file would have the following in it:
// XYZDocument.m
- (NSString *)windowNibName {
return #"XYZDocument"; // this name tells AppKit which nib file to use
}
If you were to alter this value, you would create the [NSWindowController loadWindow] error.
NSWindowController initialization methods
If you are making this call yourself (perhaps on your own subclass of NSWindowController), then you will have written a line like the following.
// XYZWindowController.m (a subclass of NSWindowController)
- (id)init {
self = [super initWithWindowNibName:#"XYZDocument"];
if (self) {
// initializations
}
return self;
}
If the string argument you've supplied does not match the name of the nib file, the same error will occur.
I ran a Clean (Cmd-Shift-K) in Xcode and that solved the issue for me.

How to parse the contents of a foreign file created with NSKeyedArchiver

I need to be able to compare two versions of a plist file created with NSKeyedArchiver. In particular, it's the "elements" file created in Xcode for a .xcdatamodeld file.
Since I have not created this file myself I can not recreate its object model. Instead, I need to understand which classes and keyed properties the archive contains.
Ideally, I want to create a tree containing strings representing the names of classes along with their property names and values. I assume that all this information is stored in the archive, so it should be possible to generically parse this archive, right?
I've read about NSKeyedUnarchiver and its delegate. I've only gotten as as as this:
Unarchive the file data:
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
unarchiver.delegate = self;
id graph = [unarchiver decodeObjectForKey:#"root"];
Here's the delegate method that gets called when an unknown class is requested. I return a proxy class here in which I hope to collect its values:
- (Class)unarchiver:(NSKeyedUnarchiver *)unarchiver cannotDecodeObjectOfClassName:(NSString *)name originalClasses:(NSArray *)classNames
{
NSLog(#"wants: %#", name);
return [ObjProxy class];
}
The proxy class implements
- (id)initWithCoder:(NSCoder *)aDecoder
in which I do not know how to proceed, not knowing the actual properties of the classes. NSCoder doesn't seem to provide any function to learn of the available keys. Is there a trick to get to them, maybe by overriding some of the lower level objc methods?
So far, with this little code shown above, when parsing the "elements" file, I only get the request for one class, "XDPMModel", and then it's done.
Any ideas how to get this working, i.e. traverse the tree deeper?
You can use PlistExplorer, it's a Cocoa Tool to inspect files written by NSKeyedArchiver.
I've done exactly this before, to decode objects stored in the preferences file for Panic's Coda. What I did was to use class-dump on the app (in your case Xcode and its related frameworks), which allows you to see the properties of the real objects, and use these to create proxy objects that match those properties. You can then use NSKeyedUnarchiver successfully and query the proxy objects for their values.
It's a fairly laborious process but it works perfectly. In my case I was working with a user defaults plist so I only had to define a couple of these proxy classes for the objects I was interested in, but I would imagine that you'll have to define quite a few for Xcode.
I'd also be very interested to know if there's a way to do this without having to go the class-dump route (possibly, as you say, via some of the lower-level Objective-C functions) because it would greatly simplify this type of reverse engineering.

Mimicking SQL Insert Trigger with LINQ-to-SQL

Using LINQ-to-SQL, I would like to automatically create child records when inserting the parent entity. Basically, mimicking how an SQL Insert trigger would work, but in-code so that some additional processing can be done.
The parent has an association to the child, but it seems that I cannot simply add new child records during the DataContext's SubmitChanges().
For example,
public partial class Parent
{
partial void OnValidate(System.Data.Linq.ChangeAction action)
{
if(action == System.Data.Linq.ChangeAction.Insert)
{
Child c = new Child();
... set properties ...
this.Childs.Add(c);
}
}
}
This would be ideal, but unfortunately the newly created Child record is not inserted to the database. Makes sense, since the DataContext has a list of objects/statements and probably doesn't like new items being added in the middle of it.
Similarly, intercepting the partial void InsertParent(Parent instance) function in the DataContext and attempting to add the Child record yields the same result - no errors, but nothing added to the database.
Is there any way to get this sort of behaviour without adding code to the presentation layer?
Update:
Both the OnValidate() and InsertParent() functions are called from the DataContext's SubmitChanges() function. I suspect this is the inherent difficulty with what I'm trying to do - the DataContext will not allow additional objects to be inserted (e.g. through InsertOnSubmit()) while it is in the process of submitting the existing changes to the database.
Ideally I would like to keep everything under one Transaction so that, if any errors occur during the insert/update, nothing is actually changed in the database. Hence my attempts to mimic the SQL Trigger functionality, allowing the child records to be automatically inserted through a single call to the DataContext's SubmitChanges() function.
If you want it to happen just before it is saved; you can override SubmitChanges, and call GetChangeSet() to get the pending changes. Look for the things you are interested in (for example, delta.Inserts.OfType<Customer>(), and make your required changes.
Then call base.SubmitChanges(...).
Here's a related example, handling deletes.
The Add method only sets up a link between the two objects: it doesn't mark the added item for insertion into the database. For that, you need call InsertOnSubmit on the Table<Child> instance contained within your DataContext. The trouble, of course, is that there's no innate way to access your DataContext from the method you describe.
You do have access to it by implementing InsertParent in your DataContext, so I'd go that route (and use InsertOnSubmit instead of Add, of course).
EDITED I assumed that the partial method InsertParent would be called by the DataContext at some point, but in looking at my own code that method appears to be defined but never referenced by the generated class. So what's the use, I wonder?
In linq to sql you make a "trigger" by making a partial class to the dbml file, and then inserting a partial method. Here is an example that wouldn't do anything because it calls the build-in deletion.
partial void DeleteMyTable(MyTable instance)
{
//custom code here
ExecuteDynamicDelete(instance);
//or here :-)
}

Resources