Cocoa Core data: cannot save Created Items in NSTableview - cocoa

I'm am a beginner in mac os x development and am trying to get started with all this.
Here is my problem : I've create a non-document based cocoa app using core data as storage. I've added an entity and attributes to the xdatamodel. In IB i've created an NSArrayController and linked it properly. I've created an nstableview binded to the nsarraycontroller. Next I added a button linked to nsarraycontroller with the " add: " method.
When I try it out, I can add and edit the items in the table.
Here comes the problem: Core data is supposed to save everything automatically, but to make sure i linked the "save" button in the menu to the appdelegate and to the " file's owner" , first responder, application... everything possible ( with both " save :" and " saveaction:" methods ).
And still it doesn't save when clicking save: when I restart the cell created ( and renamed ) are gone.
And also, I didn't even edit the source code yet; core data for such simple tasks is supposed to only need Interface builder.
Please help me for this, I haven't found any threads resolving this problem.
Thank you in advance.

To save the changes, you'll have to call save: on the managed object context.
If you look at the CoreDataBooks example, you'll see how they call it like this as a result of the user pressing save:
- (IBAction)saveAction:(id)sender {
NSError *error;
if (![[self managedObjectContext] save:&error]) {
// Update to handle the error appropriately.
NSLog(#"Unresolved error %#, %#", error, [error userInfo]);
abort(); // Fail
}
}

Related

How to use NSObjectController and Managed Object Context using Cocoa Bindings

Searched entire Internet but couldn’t find the modern solution for my problem.
I want to use NSObjectController in pair with Core Data through Cocoa Bindings and struggle to set it up properly. Worth noting that I’m using latest version of Xcode and Swift.
What I’ve done:
For testing purposes I’ve done the following:
Created an macOS app with “Use Core Data” option selected (the app is not document based);
Dragged 2 NSTextFields into the Storyboard Dragged NSObjectController to the view controller scene;
Added Employee Entity to Core Data model with 2 attributes “name” and “surname”;
Done everything from the answer in How do I bind my Array Controller to my core data model?
Set NSObjectController to entity mode and typed in “Employee”,
Prepares Content selected, Use Lazy Fetching selected so all three options checked;
Binded the NSObjectController’s Managed Object Context in bindings inspector to the View Controller’s managedObjectContext;
Binded NSTextFields as follows: Value - Object Controller, Controller key - selection, Model Key Path - name (for 1st text field) and surname (for 2nd).
That’s it.
First set of questions: What I did wrong and how to fix it if it’s not completely wrong approach?
I’ve read in some post on stackoverflow that doing it that way allows automatic saving and fetching from Core Data model. That’s why I assumed it should work.
So here is a Second set of questions:
Is it true?
If it is then why text fields are not filled when view is displayed?
If it is not then how to achieve it if possible (trying to write as less code as possible)?
Third question: If I used approach that is completely wrong would someone help me to connect Core Data and NSObjectController using Cocoa bindings and show me the way of doing so with as less code written as possible using the right approach?
Taking into account that there no fresh posts about this topic in the wilds I think the right answer could help a lot of people that are developing a macOS app.
Thanks in advance!
I think your basic approach is correct, although it is important to understand that you need a real object, an instance, in order for it to work.
Creating a NSManagedObject subclass is generally desirable, and is almost always done in a real project, so you can define and use properties. You can do it easily nowadays by selecting the data model in Xcode's Project Navigator and clicking in the menu: Editor > Create NSManagedObject Subclass…. Technically it is not necessary, and in a demo or proof-of-concept, you often muddle through with NSManagedObject.
Assuming you are using the Xcode project template as you described, wherein AppDelegate has a property managedObjectContext, the following function in your AppDelegate class will maintain, creating when necessary, and return, what I call a singular object – an object of a particular entity, in this case Employee, which your app requires there to be one and only one of in the store.
#discardableResult func singularEmployee() -> NSManagedObject? {
var singularEmployee: NSManagedObject? = nil
let fetchRequest: NSFetchRequest<NSManagedObject> = NSFetchRequest(entityName: "Employee")
let objects = try? self.managedObjectContext.fetch(fetchRequest)
singularEmployee = objects?.first
if singularEmployee == nil {
singularEmployee = NSEntityDescription.insertNewObject(forEntityName: "Employee", into: self.managedObjectContext)
}
return singularEmployee
}
Then, add this line of code to applicationDidFinishLaunching
singularEmployee()

How to set iAd Delegate to new View Controller

I am developing an application using Xcode 7 and Swift 2. I recently discovered an error in my code. In the debugger log (I think that is what it is called) , it printed this:
[AppDeveloper] ADBannerView: Unhandled error (no delegate or delegate does not implement didFailToReceiveAdWithError:): Error Domain=ADErrorDomain Code=7 "Ad was unloaded from this banner" UserInfo={ADInternalErrorCode=7, NSLocalizedFailureReason=Ad was unloaded from this banner, ADInternalErrorDomain=ADErrorDomain}
I did some research and found out that I needed this code:
iAdBannerView.delegate = self
In my viewDidLoad method. I tried it, and I no longer recieved the error. However, I have two viewControllers. Both contain iAds. In the original view controller, ViewController.swift, the code workds. In the view controller that I later added, AboutViewContoller, I get this error:
Cannot assign a value of type 'AboutViewController' to a value of type 'ADBannerViewDelegate?"
Could someone please show me my error in my code?
Earlier, I had:
class AboutViewController: UIViewController {
I forgot the ADBannerViewDelegate. The correct code is:
class AboutViewController: UIViewController, ADBannerViewDelegate {
Thanks to Charles A. and Daniel Storm for helping out!

Change UILabel from appDelegate

I want to do some stuff from the appDelegate in Xcode. One of these things are to change a UILabel.
ViewController *viewController = [[UIStoryboard storyboardWithName:#"Main_iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"id"];
viewController.label.text = #"heeej";
I was told this would do the trick. Doesn't work. Label doesn't change. Does anyone know what the problem is?
There are several problems:
Don't do anything in the AppDelegate except for loading the window an the initial view controllers (if needed).
You are instantiating a new view controller in the first line. I assume you already have a view controller and you want to change the label in that view controller. Than you need a reference to that view controller and use this reference to send messages to it.
The label should not be a property of the view controller. You should try to follow the design pattern Model-View-Controller or the pattern Model-View-ViewModel. Ask you preferred search engine what those are if you don't know.
id as an identifier for anything in Objective-C is a bad idea because this is used as an object type.
Edit: You don't need a reference to change a property in the view controller. Use notifications to update the label. The system sends a notification with the name UIApplicationWillEnterForgroundNotification' (see [here][1]). Add the view controller as an observer to the[NSNotificationCenter defaultCenter]` for this name and react on the notification. Read the Apple documentation if you don't know what I am talking about.

Load Different View Controllers in the Master-Detail App template

I am developing a master detail application using Xcode 4.3.3, now in the master view controller i have managed to load an additional view controller called "Fav Real"When this view controller loads, it will contain different items taken from an sqlite database into a tableViewController. My problem is here, i need when i click on any loaded row, to load a different viewController into the detailViewController, to load another view controller instead of the first one. I am actually lost, i tried to do the following schema but i have no idea how to do my goal...Any help will be highly appreciated.
As it shows, the items will load correctly in the FavReal tableView , but my goal is when i click at any row, the "Details" showing in the right will load instead of the DetailsViewController.I tried this code in the FavReal.m but i always get : " Application tried to push a nil view controller on target .
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Details * vc4 = [self.storyboard instantiateViewControllerWithIdentifier:#"Details"];
[self.navigationController pushViewController:vc4 animated:YES];
}
Thank you for your time, if any further details are needed please tell me
In case anyone was having the same problem as i was, the only solution i found is not to load a different view controller and replace the original detailViewController, but the actual solution was to create a new storyboard and make it appear when the Favorites button is clicked, this way you'll have a nice stylish effect and keep your data presentation accurate. To do so use the following lines of code :
UIStoryboard* storyboard = [UIStoryboard storyboardWithName:#"SecondStoryboard" bundle:nil];
UIViewController* initialHelpView = [storyboard instantiateInitialViewController];
initialHelpView.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentModalViewController:initialHelpView animated:YES];
You have the freedom to change the modal presentation as u prefer.Best of luck

reference between app controller and window controllers

at the risk of a public flogging, I was hoping someone could clarify my understanding of communicating between the app controller and a window controller. Here is the scenario using xcode4.
using the default AppDelegate.h and .m as the "controller" (which is also a delegate to MainMenu.xib). Have an ivar called int counter.
Created page.xib and PageController.h and .m (subclass NSWindowController). Imported it into AppDelegate.m
Used IBAction to create and view the page object. Like this:
if (!page1) {
PageController *page1 = [[Page
if (!page1) {
page1 = [[PageControoer alloc] initWithWindowNibName:#"page"];
}
[page1 showWindow:sender];
So the new window pops and we can press buttons, etc. The code for the new window is all in PageController.h and .m. and things basically work.
That is the context, here is where I'm confused.
a) question: let's say I want to access that original ivar in AppDelegate.h called counter from PageController. Either retrieving or updating the variable. What approach would I take?
b) confirm: let's say I'm back in the AppDelegate and want to get access to a selector from page1. I believe I can do this as so: [page1 runaction]; or [[page1 variable] setStringValue:#"hello"];
(this complies but I'm not sure it really works because I can't get the changes into the xib view.)
ok and the stumper. Say another view was created with another view controller call it Page2Controller.h and .m.
c) how should data flow between page and page2 -> via the AppDelegate or directly? what would the syntax look like to connect them together?
I've been following tutorials, but they don't really cover this back and forth messaging. Thanks for all the help!
a) Generally, if you want to have data that is accessed by your controllers, it should be in a model which they are given access to in some way. You can access things in the app delegate using this method:
AppDelegate* appDelegate = [[NSApplication sharedApplication] delegate];
[appDelegate <some method>];
b) I don't understand what you're asking. If the app delegate has a pointer to page1, then yes, you can call it directly.
c) Again, you should have a data model of some sort. The controllers should update the data model when the user changes the view. You can use notifications, IBActions, and direct calls to do the updating, for example. You should look up the Model, View, Controller design pattern.

Resources