I have a class called TextFieldMagic which handles the NSTextField manipulations, animation,validation etc.
I want to get the NSTextField instance from tne TextFieldMagic class in my AppDelegate. I tried the following and I couldnt get it working. I'm just getting (null)
- (IBAction)testHide:(id)sender {
TextFieldMagic *textFieldMagic = [[TextFieldMagic alloc] init];
NSLog(#"%#",[textFieldMagic.textField stringValue]);
}
Of course, I could create an IBOutlet for NSTextField in my AppDelegate to get this working, but I want to understand how to do it w/o creating an IBOutlet in AppDelegate.
That's not the correct approach. With MVC, which is the design pattern adopted with Cocoa apps, the NSTextField is part of the View and should be used exclusively by the Controller in order to populate the Model.
In other words you need to expose some or all of the Model data for other classes to use, and you should not be attempting to use the same View from multiple Controllers.
Related
Still learning so I could really use some help from you more seasoned folks. I'm learning more about the MVC model and trying to implement this with CoreData. My test application has the AppDeligate, MainController and a MocManager. All CoreData stuff is moved to the MocManager.
On the xib I have an NSTable, an NSArrayController and a NSButton.
In MainController, I have an instance of the MocController with a simple method to add a name to the database.
-(IBAction) addPerson:(id)sender{ [manager addperson:#"Sam"]; }
This method is called when the NSButton is pressed. Pressing the NSButton does add the name to the database, however it does not update the table. If I close the App and reopen, the name will appear in the NSTable, so the adding method is good and is working.
I tried both of the following (Separately):
Linked the NSArrayController to MainController through an IBOutlet
Linking the NSArrayController to MocManager through an IBOutlet
In both cases, I used [ArrayController rearrangeObjects] method after the save - the NSTable still does not update.
--[EDIT]----
Appears to be a bindings issues as pointed out by Vadian - but I cannot seem to figure out where/why.
In a previous App I successfully moved the coredata stack in to the MainController, all bindings appear to be working properly.
For this test App, I moved the coredata stack to it's own controller - "MocManager".
In MainController I created an instance of MocManager with:
MocManager* Manager; //This is in .h
manager = [[MocManager alloc] init]; //This is in .m init method
Data loads in to table on startup, but will not sync when using addPerson method in MainController.
Also, I connected an NSButton directly to the remove method on the NSArrayController - the items are removed from the NSTable but not saved, they reappear when App restarted. This all further points to the bindings issue.
Any pointers/thoughts/help would be greatly appreciated.
--[EDIT - SOLUTION]-----
Thanks to Vadian for pointing me in the right direction, it was in fact my bindings.
In the NSArrayController in the XIB I needed to bind it properly to the correct ManagedObjectContext. In my case it is to manager.ManagedObjectContext.
Hope this helps someone.
I am writing a test project to learn to write everything in code. I want to do this way so that I can better understand what the Elements in Storyboard do for me behind the scene's
In my project I have several UIViewControllers which share the same UI elements. For Example I have a UITool bar at the top of the screen with several buttons in it.
Now I want to put that UIToolbar in a separate class so that I do not have to write it all out or copy n paste it in every controller.
Now I know I can achieve this by doing this:
#import "General_Add_ons.h" //the UIToolbar is properly set up in this file
#interface FirstViewController : General_Add_ons
and then I just use [self topToolBar]; //topToolBar is the name of the toolbar
Now I just want to clarify is this the best and or only way to this?
Somehow I feel I should be able to do this:
General_Add_ons *gao = [[General_Add_ons alloc] init];
[gao topToolbar];
Am I thinking about this the wrong way? The first way seems to be limiting in case I have multiple external classes.
Thanks in advance.
Your approach seem correct. If you have several UIViewController instances that need the same UI elements or other controller code, you can put those elements in a UIViewController subclass. In your case, I believe the class General_Add_ons is the UIViewController from which your subclasses will inherit.
This class (your General_add_ons) should have a property for the reusable toolbar, e.g.
#property (nonatomic, strong) UIToolbar *toolbar;
As an aside, class names in Cocoa, by convention are: prefix+capitalized words without underscores. Apple has a great reference on naming conventions.
EDIT
For clarification, you can subclass your custom subclass as many times as you need. For example in my code, I have a class CCFViewController that encapsulates common properties and behaviors that I want all of my view controllers to have. In the project, then, all of the view controllers inherit from that parent controller. Similarly, your toolbar will live in the superclass and the other controllers inherit from it.
I am not 100% sure but i think you should try it this way:
General_Add_ons *gao = [[General_Add_ons alloc] init];
[gao.topToolbar anypossiblemethodcall];
I have two view controllers and nibs. I populated one view controller with a toggle switch and declared this in its header file:
#public UISwitch *toggleSwitch;
and exposed it as a property like this:
#property (nonatomic,retain) IBOutlet UISwitch *toggleSwitch;
I also connected the switch with toggleSwitch outlet. Then I used this switch in my other view controller like this :
theViewControllerWhereIDeclaredTheSwitch.toggleSwitch.on = YES;
Though everything worked fine with the switch being ON by default but when I switched off the switch it threw an exception: "Thread 1: signal SIGABRT" in the main.m file. I get this error quite often while working with Xcode, this error is a real pain in my ass. Please help.
You should not share UI elements over multiple UIViewControllers.
A better approach would be to share a BOOL or even encapsulate the state in your own object inheriting from NSObject and pass that between the 2 UIViewControllers.
#werner is right.
When programming a Controller and a View associated, you are implementing the NVC Pattern.
The idea is that you have this Controller object that is the brain between a View and a Model that holds datas.
Hence what you should perform in your application is not share the switch state but update a BOOL value in your Model when triggering the switch and share the Model with the two Controllers in order to know the value in the two Controllers.
(CF: wikipedia)
I am still new to iOS development and I wanted to know how to accomplish something. What I have is s UIViewController objects FirstController and SecondController. In the NIB file for FirstController I have a UITextField. In the NIV file for SecondController I have a UILabel.
What I want to do is update the UILabel with a new value as I update the UITextVew. So far, I have the following in my FirstController:
- (IBAction)tbxName_EditingChanged:(id)sender;
In the SecondController I have the label in an Outlet Collection like so:
#property (retain, nonatomic) IBOutletCollection(UILabel) NSArray *lblName;
Now, I have made the collection because I intend, in the future, to add more labels that will need to be changed and have all have the same value.
So, what I was thinking that I have to do is place a reference of my SecondController into my FirstController so that I can then run a custom 'update' method. Something like this:
FirstController *viewController1 = [[[FirstController alloc] initWithNibName:#"FirstController" bundle:nil] autorelease];
SecondController *viewController2 = [[[SecondController alloc] initWithNibName:#"SecondController" bundle:nil] autorelease];
viewController1.secondView = viewController2;
// do the rest to load the views...
Now, I have learned that a lot of the stuff I have learned, in .net., is not the way you do things in Objective C. I was wondering if this is what I have to do, or is there another way that I am not finding with Google?
Thanks for any help, and I hope that I explained this clearly enough.
Solving problems like these in a predictable, proven way is the whole point of the Model-View-Controller design pattern. The point is, you want the first UIViewController to update the model, which will signal the second UIViewController to update its view.
I'd suggest having a model somewhere. Either by using a singleton, first initialized in the app delegate, or core data, which is a little more advanced but very powerful.
I am creating a Ipad with two view controllers. One view controller is FirstViewController and the other is SecondViewController. In FirstViewController, I fill an array with numbers. Now in my SecondViewCOntroller, I have a table view. I want to put the array that I created in FirstViewController into my SecondViewController table view? How do I do this? Please help me!
You need to reference the NSArray object in the SecondViewController, you could do this by means of a delegate. A delegate is an instance variable that contains the pointer to the delegate, in this case the FirstviewController. Then in FirstViewController you add a property for the NSArray if its an instance variable, and call delegate.someArrayName in the secondviewController
This approach breaks MVC. You can't have data array as an instance variable in your FirstViewController. You'd have to store data in some other class (the M part of MVC). You fill that M part from FirstViewController (the V part) and then access that filled M part from SecondViewController. This way you won't be dependent on how those two controllers relate to each other (parent/child or siblings or whatever other hierarchy you may think of).
The most simple approach I can think of is storing serialized array in a plist file. Storing the file in first and accessing it in the second view controller.
The most straight forward approach will be to create a property on SecondViewController.h like:
#property (nonatomic, retain) NSMutableArray *yourArray;
and in SecondViewController.m, put:
#synthesize yourArray;
At this point you have created a property on SecondViewController. Now, when you are about to open Second View Controller, just create its instance and do something like following:
secondViewController.yourArray = array;
[self.navigationController pushViewController:secondViewController];