updating table view with data in array? - objective-c

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];

Related

Getting NSTextField Value from another Class

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.

Bind Label to class' property

I'm trying to bind a label (NSTextField) to a class' property. In Interface Builder I bind the label's Value to File's Owner with Model Key Path = self.aString.
File's Owner is a NSViewController's subclass with aString defined as: #property (nonatomic, strong) NSString *aString;
The label is placed inside a View Based NSTableView filled at run-time by a binding with a managed object context.
When i call [self setAString:#"..."] or [self setValue:#"..." forKey:#"aString"] in the class' implementation, nothing changes in the table view. However if the label is placed inside the view it works. Why?
This is a limitation of view-based table views, and from what I know the only way to fix it would be to set TableView.delegate to your File's Owner (or another object if you're trying to bind to that instead).
(I'm hoping for a better answer to explain why, because I don't know why this is the case)
Cake's answer is a good workaround.
I solved by subclassing NSTableCellView and adding to it a NSString property. Then i bound the value of the label to the Table Cell View with the name of the property as key.
You probably don't have direct access to it when it's inside the tableview. Try storing a reference to the tableview and then calling the label. So if your table had a reference named t, connect the label to the table and then:
t.labelName.text = #"string" Although, if it's inside a cell in the table you may need to use cellForRowAtIndexPath and reference the label inside a subclassed cell. If you don't know how to do this I can post some code.

Reloading UITableView from another class?

This is a question rather many people have asked, especially here on StackOverflow.
Reloading the data on the table view is easy, [self.myTableView reloadData];, myTableView is the instance of my UITableView, since I am using a UIViewController instead of a UITableViewController.
I want to reload the table view from another view controller after I have updated the data (from Internet). The data is contained in a property list. I have tried using protocols, notifications and some other things like putting it in viewDidAppear:. Nothing have worked for me.
Is it something I haven't thought about or have I just done some of the methods wrong? The help is much appreciated!
If you want access to a UITableView object, or just about anything else for that matter, from another class, you can make it accessible using a property:
ClassA.h
#interface ClassA {
UITableView *tableView;
}
#property (nonatomic, readonly) UITableView *tableView;
#end
ClassB.m
- (void)reloadTableInOtherClass {
[classAVariable.tableView reloadData];
}
Using observer pattern + notification is a good way. And to let your view controller decide when to reload data is also a good practice.
Why notification does not work. Did you use addOvserver: ?

Accessing parent view controller (custom) properties

I have written a UITabBarController subclass (called MainViewController) and added a few instance variables, specifically a venue of type Venue. Each tab of the MainViewController needs to access the venue variable of the MainViewController. In the first tab, a UIViewController subclass named HomeViewController, I wrote my viewDidLoad method and tried to output to NSLog with both...
NSLog(#"%#", self.parentViewController.venue.name);
and
NSLog(#"%#", self.tabBarController.venue.name);
But XCode gives the error
error: request for member 'venue' in something not a structure or union
I can access the venue property from within MainViewController just fine so have ruled out an error there. The iPhone simulator does see both self.parentViewController and self.tabBarController as an instance of MainViewController. The line...
NSLog(#"%#", self.tabBarController);
outputs...
2009-06-05 17:54:46.502 Venue[29729:20b] <MainViewController: 0x536600>
Since it's seen as a MainViewController instance, I doubt using casting would help. Is my only other option to initialize the HomeViewController with a copy of the venue or am I just doing something completely wrong with 'self.parentViewController.venue.name'? Thanks, Rob
You're doing something completely wrong. parentViewController is declared as a UIViewController. NSLoging it outputs its real type due to the wonders of polymorphism.
UIViewController doesn't have a Venue member. Your MainViewController does. Casting it is, in fact, the right answer. Make sure to import MainViewController.h as well.
#import "MainViewController.h"
[...]
NSString *name = ((MainViewController *)self.parentViewController)).venue.name;
Also make sure, of course, that venue is declared as a #property of MainViewController, and name is a #property of Venue.
int currentVCIndex = [self.navigationController.viewControllers indexOfObject:self.navigationController.topViewController];
//previous view controller
AccountViewController *account = (AccountViewController *)[self.navigationController.viewControllers objectAtIndex:currentVCIndex - 1];
account.property = object;
[account doSmthng];
Your NSLog() statement is "seeing" it as a MainViewController because that's what the object actually is. The problem you're having though, is that the compiler doesn't actually realize this because the parentViewController property is declared as a plain old UIViewController. Even though you're actually returning a subclass of it, as far as the compiler knows you're trying to call that method on a UIViewController, and it's going to complain. Casting it to a MainViewController will solve the issue.

Communicating between view Controllers

one of my view controllers has several UISwitches, and I want another view Controller to be able to access the values of the UISwitches for If/and statements. How do I do this in Objective-c?
This is a bad idea as it would create an unneeded dependency between the view controllers.
If you still want to do it, just pass a reference of the first view controller with the switches to the second view controller. Then, in your second view controller just access the corresponding UISwitch's on property.
However, instead of going that route, I strongly suggest that you create a custom class to hold the boolean state of each UISwitch. An instance of this class could either be a singleton, or contained in the application delegate. See this answer for how to do it with both approaches.
A custom class is better because a UISwitch is just a way to represent some property in your data model. And if tomorrow you replaced the UISwitch with another fancy
control, the second view controller should still continue to work. Both view controllers have a reference to an object of this custom class. Whenever there is a change, the first controller updates this object.
The class interface could be something like this:
#interface DataValues : NSObject {
BOOL first;
BOOL second;
BOOL third;
}
#property BOOL first;
#property BOOL second;
#property BOOL third;
You probably don't want to do that. If you want a second ViewController to have different behavior based on switches thrown in the first, you should just bind the switches to User Defaults, which you can read anywhere in your app.
http://icodeblog.com/2008/10/03/iphone-programming-tutorial-savingretrieving-data-using-nsuserdefaults/