I have subclassed both NSDocumentController and NSDocument. Is there a way to get to the MyDocumentController from MyDocument?
Currently I have an outlet in my AppDelegate that connects to MyDocumentController, so I can get to it that way, but was wondering if there was a more directly accepted way?
You don't need an outlet or anything like that. NSDocumentController is a singleton, meaning that there's only ever one instance that manages documents for the whole app. Because you have that custom document controller in your nib, it's the first to be instantiated and therefore becomes the shared document controller. So all you have to do is retrieve the shared document controller:
In Objective-C:
MyDocumentController *sharedController = [MyDocumentController sharedDocumentController];
In Swift:
let sharedController = MyDocumentController.shared()
Related
I am still relatively new to development for Windows Store Apps in XAML/C# and I'm currently dealing with a very random and intermittent problem with an app I have written.
Firstly a quick overview of how my app works - user logs on once a day, downloads data from web service and stores the data in xml files. Each time the app opens/resumes the data is loaded from xml, deserialized and stored in memory in the Application.Resouces Resource Dictionary.
The objects I am storing are my own classes which contain Observable Collections of other classes. I have declared these in App.xaml
<localdata:MyClass x:Key="MyClassResource">
When a page needs this data I reference it using
MyClass myClass = (MyClass)App.Current.Resources["MyClassResource"];
and bind it to controls. The user updates the data and these changes would also be saved to file periodically.
I am now starting to doubt whether this is the correct approach for storing my data.
Every so often the users reports problems with the stored data - I don't have enough details to fully discuss the specific problem right now but I wanted advise on whether it is fine to store my own objects in the Application Resource Dictionary.
There's nothing wrong with your approach. It is actually a very common way to create and access the viewmodel. There is an excellent blog post by Paul Stovell describing different approaches to create and access the viewmodel.
Create viewmodel from code-behind within the view
Inject the viewmodel as dependency into the view
Assign viewmodel to view's DataContext property
Set viewmodel via XAML to DataContext property
Define viewmodel as resource in XAML
Use a view model locator in XAML
DataTemplate property in XAML
DataTemplate and view class in XAML
The referenced article describes all 8 approaches with examples. Your approach is number 5.
I have two windows, one is a table view to display content. One is a window for inputting content.
I have an NSTextField binded to a property in my app delegate. When I change a value in the text field, the app delegate property will change. However, if I go the other way and programmatically change the property's binded key, the value of the text field does not update. However, it does in the table view.
What is going wrong here? How can I update text field?
EDIT:
I tried all 3 of these with the same result
[_addEntry setValue:#"Chet" forKey:#"payee"];
[_addEntry setPayee:#"chet"];
_addEntry.payee = #"chet";
EDIT:
Here's a simple example to elaborate on my point
https://dl.dropboxusercontent.com/u/48014761/test.zip
the label and the textfield are bound to the "str" property. It is initially null. press log to see that in the console. press change str button to change the string. Log to verify. Note that the label and the textfield do not update!
EDIT:
"What am I trying to accomplish?"
Here's the project I am working with:
https://dl.dropboxusercontent.com/u/48014761/Write-Offs.zip
I am trying to use Cocoa Bindings as much as possible. I have a table with a bunch of data. However, each entry is going to have an array of images associated with it. Thus, when I add a new entry, I need to open up a new window so I can set the properties of that entry (rather than through the table) along with upload some images.
I am not sure I am implementing the addEntryWindow correctly. It seems like I should create and destroy the window each time I open and close it. This doesn't appear to be happening.
Also, [[self addEntry] setDate:[NSDate date]]; doesn't seem to fix the problem for me.
Thanks
Chet
How are you programmatically changing the field? Are you using KVO? Is the field inside of a NSManagedObject instance?
Bindings work through KVO. Core Data disables some aspects of KVO for its own internal uses and you might be tripping over one of those.
Update your question with the code sample and lets see what is going on.
Update
Both windows don't necessarily need to be in the same xib but they do need to be talking to the same instances. Ideally they should both be talking to the same instance of NSManagedObject and therefore talking to the same NSManagedObjectContext.
Who is the owner of each window?
Is the owner the same?
If not, is a new Core Data stack being created?
Update
In your test, I was able to correct it by how you were editing the property
- (IBAction)press:(id)sender {
[self setStr:#"this"];
}
You were accessing the iVar directly instead of the property. When you access the iVar directly KVO does not fire.
In addition, in your xib files you were accessing self.str which is unnecessary. It should be just str.
Are you doing any direct property access in your actual project?
Update
You can do a get accessor and then a set accessor:
[[self addEntry] setPayee:xxx];
Based on the variables you are using I wonder what you are trying to accomplish. Can you post the exact code of the programmatic change you are trying to enact?
is there a simple and efficient/fast way to query a managedobjectcontext to get an array of all the managedobjects in the context that have not yet been added to the persistent store?
i ask this because i would like to be able to save nsmanagedobjects that have been added to the MOC only if they conform to certain criteria. basically i want to be able to do this so that if some unexpected event happened before my managed object attributes were properly populated, i can catch this fact and purge the object(s) before saving the context. given the complexity of the navigation possible in the app, i'd like to have a look at the data to be sure they are good before i save.
i suppose i could also do this with some kind of validation rule and a flag field that doesn't get set until i am sure the user has added all the data to the record, but i don't yet know how to implement this...
any help much appreciated.
The insertedObjects method of NSManagedObjectContext
returns the set of objects that have been inserted into the context but not yet saved in a persistent store.
I have an iPad app, built with XCode 4.5, Storyboard, Core Data (using MagicalRecord) and iOS 6. I have two Entities, each with multiple attributes. The first entity has a one to many relationship with the second entity.
In the MagicalRecord docs, I don't see how to persist the data to the second entity; I read somewhere that Core Data generates it's own key and indexes. I know from past use of SQLite that I would need to set the key from the first entity to be able to access the second entity.
[UPDATED] Here is the modified code but it doesn't work either. I have previously selected a row in didSelectRowAtIndexedPath in another class. I assume that set the localContext. Any ideas why this is not working?
- (IBAction)saveAppointment:(UIButton *)sender {
AppointmentInfo *newAppointment = [AppointmentInfo MR_createInContext:localContext]; // create the entity
newAppointment.aStartTime = selectedStartDate;
newAppointment.aEndTime= selectedEndDate;
[localContext MR_saveNestedContexts];
}
You need to create your Entity in the proper (ie. localContext) context:
[AppointmentInfo MR_createInContext:localContext];
I found the problem... seems that I had the store setup incorrectly... I removed the parent pointer from AppointmentInfo and added the "class" information. Works like a champ now... thank you for your time, tho'.
I'm using AFIncrementalStore to connect my iOS application to my REST API. When I load my initial view controller, I create an NSFetchRequest that loads the latest 100 Events (NSManagedObjects) into view. The problem is that each Event has a 1:1 relationship with a Group object, and as soon as the Event is loaded, the incremental store is asked to fill that Group object, which in my case triggers an individual request to the server for each of the 100 Events.
I can see a couple ways to solve this problem, such as not requesting Groups from the server if they are already saved locally, caching the network request, or not storing the relationship in the NSManagedObject. But ideally, the Group object could start out as a Fault and only request to be filled once one of its field is accessed, similar to what happens with one-to-many relationships. Unfortunately I can't find any documentation that says how to force a one-to-one relationship in core data to be lazy-loaded. Is it possible?
Maybe this is what you are looking for?
From AFIncrementalStore.h:
/**
Returns whether the client should fetch remote relationship values for a
particular managed object. This method is consulted when a managed object
faults on a particular relationship, and will call
`-requestWithMethod:pathForRelationship:forObjectWithID:withContext:` if `YES`.
#param relationship The relationship of the specifified managed object
#param objectID The object ID for the specified managed object.
#param context The managed object context for the managed object.
#return `YES` if an HTTP request should be made, otherwise `NO. */
- (BOOL)shouldFetchRemoteValuesForRelationship:(NSRelationshipDescription*)
relationship forObjectWithID:(NSManagedObjectID *)objectID
inManagedObjectContext:(NSManagedObjectContext *)context;
If so, you could set this with
- (BOOL)shouldFetchRemoteValuesForRelationship:(NSRelationshipDescription *)relationship forObjectWithID:(NSManagedObjectID *)objectID inManagedObjectContext:(NSManagedObjectContext *)context
{
return NO;
}
in your AFRESTClient <AFIncrementalStoreHTTPClient> subclass.
I've been struggling this as well. Looks like one-to-one relations will always be eager loaded. One way around this could be to declare it as a one-to-many relation so that it automatically does a lazy load instead. Then in your model class, you can have a method that returns the first one in the set.