Access class variable from another class - objective-c

I have a UITabBarController that manages two ViewControllers. The first is a UIViewController that allows the user to change game settings. The second is a GLKViewController that runs the game simulation.
I'm trying to enable the Game ViewController to fetch the settings from the Settings ViewController. I have a Slider on the Settings View that represents "Speed".
I have a reference to the other controller, but I'm unable to expose the variable that backs my Slider properly.
SecondViewController.h
#interface SecondViewController : UIViewController{
IBOutlet UISlider * mySlider;
}
property (nonatomic,retain) IBOutlet UISlider * mySlider;
#end
SecondViewController.m
- (IBAction) mySliderWasMoved:(id)sender;
#implementation SecondViewController
#synthesize mySlider;
- (IBAction) mySliderWasMoved:(id)sender{
};
ThirdViewController.m
NSArray *tmpVCs = self.parentViewController.tabBarController.viewControllers;
UIViewController *tmpVC = [tmpVCs objectAtIndex:1]; //obtain handle to SecondViewController
//NSNumber *mySpeed = tmpVC.mySlider; //doesn't see mySlider
NSNumber *mySpeed = [tmpVC mySlider]; //doesn't see mySlider
I'm new to this, and there are many aspects of my project to learn - so I'm not trying to learn how to manage data at this time. I just need to know how to access an instance variable

As mention on the comments,
Use NSDefault to save the value on slider changed. On the very first time of loading your application, you will want to set a default value.
Use Singleton Object to store value.
We understand that, quoting from you " not trying to learn data persistence at this time. Nor do I need architecture direction.", but the rule of thumb here is that you probably will be able to access the instance variable in some way or the other but i think having the best approach will benefit you greatly.
Just my 2 cent.

Fort the benefit of others: I grabbed a handle to the other class, but I hadn't declared the return type as the correct type of class.
Replace:
UIViewController *tmpVC = [tmpVCs objectAtIndex:1];
With:
SecondViewController *tmpVC = [tmpVCs objectAtIndex:1];
Now I have access to the properties that are specific to the SecondViewController.

Related

Objective-C - Call a method that modify a textField from another class

I have two questions :
When I try to call a method from different class (this method modify a textfield after having checked a condition) the method is well called (the NSLog in statutInternet works) but the TextField isn't modified..
When I do it from the (IBAction)internet method it works .. Any solution ?
Why Xcode want me to called my variables (like internetTextfield) with a _ before it ?
WindowsController.h
#import <Cocoa/Cocoa.h>
#interface WindowController : NSWindowController
#property (assign) IBOutlet NSTextField *internetLabel;
- (void)statutInternet;
- (IBAction)internet:(id)sender;
#end
WindowsController.m :
#import "WindowController.h"
#implementation WindowController
- (IBAction)internet:(id)sender;
{
[self statutInternet];
}
- (void)statutInternet;
{
NSLog(#"Callfunctionworks");
if (condition) {
[_internetLabel setStringValue:#"TxtFieldWorks!"];
}
}
I try to call the method statutInternet with this from another class :
WindowController *fenetre = [[WindowController alloc] init];
[fenetre statutInternet];
When I try to call a method from different class it doesn't work:
That's because, You're making another WindowController instance using this code:
WindowController *fenetre = [[WindowController alloc] init];
This is another new separate instance of same class, which I guess you're not showing. So you want to take reference to the window that's already showing rather than making a new instance.
Why Xcode want me to called my variables (like internetTextfield) with a _ before it ?
That's because when you declare variable using #property it does three things:
Makes an internal variable by adding the conventional underscore (_) to the start of the variable name. That's why you've _ as prefix of your variable.
Makes a setter-getter methods.
Takes the keywords you used (ie. assign, strong, weak) in account while implementing the setter-getters.
You can read a good discussion here: #property and retain, assign, copy, nonatomic in Objective-C
The NSTextField (and all of the other UI items) is not created yet when you call statutInternet method.
When your window loaded, your views will be ready :
_fenetre = [[WindowController alloc] initWithWindowNibName:#"WindowController"];
[_fenetre showWindow:_fenetre.window];
[_fenetre statutInternet];

Using a button to create a custom class instance and show it in an NSTableView

Im stuck on this problem and it's driving me crazy. What I am attempting to do is have a button click create an instance of a custom class, set it's variables, add it to an NSMutableArray, and display it in a table view. So far it seems that I have everything working except having the info display in the table view.
My custom class TradePaperback just has three NSString properties: title, volume, and publisher.
Here is the code for my header and implementation files:
Header:
#import <Cocoa/Cocoa.h>
#interface AppDelegate : NSObject <NSApplicationDelegate>
#property (nonatomic, strong) NSMutableArray *tradeArray;
#property (weak) IBOutlet NSTableView *tableView;
- (IBAction)addTrade:(id)sender;
#end
implementation file:
#import "AppDelegate.h"
#import "tradePaperback.h"
#interface AppDelegate ()
#property (weak) IBOutlet NSWindow *window;
#end
#implementation AppDelegate
-(NSMutableArray *)tradeArray{
if (!_tradeArray){
_tradeArray = [[NSMutableArray alloc]init];
TradePaperback *avengers = [[TradePaperback alloc]init];
avengers.title = #"Avengers";
avengers.volume= #"volume 01";
avengers.publisher = #"Marvel Comics";
[_tradeArray addObject:avengers];}
return _tradeArray;}
- (IBAction)addTrade:(id)sender {
TradePaperback *newTrade = [[TradePaperback alloc]init];
newTrade.title = #"New Trade";
newTrade.volume = #"Volume Number";
newTrade.publisher = #"publisher";
[_tradeArray addObject:newTrade];
NSLog(#"added");
NSLog(#"number of items in array is %ld", _tradeArray.count);
[_tableView reloadData];}
#end
My table view is hooked up using bindings. It seems that everything is hooked up correctly since the avengers instance of TadePaperback that i put in shows up when I run the program. As I click the add button I can see from the log in the console that the array is having items added to it, but they just won't display.
Why would the tableView show the first item in the array, but none of the rest?
Here is a picture of the program after running and clicking the add button a couple of times.
program running
I would greatly appreciate any help or advice you guys could give. Thanks in advance.
-Jack
If you're using bindings to populate a table view, you're almost certainly using an NSArrayController to manage the table's content. If you want to add an object to the array controlled by this controller (your tradeArray object), you should do so indirectly: add to the array controller, which will in turn update your array. NSArrayController provides a number of add... or insert.. methods; decide which one suits you best, and use it to replace your call to [_tradeArray addObject:...].
The reason this approach works, and yours doesn't is because this engages the key-value coding/observing machinery that underpins bindings. Your approach essentially adds the object behind the array controller's back - it's not KVO/KVC-compliant, so the array controller remains unaware of the change. Cocoa does provide you with a way of editing the original array in a KVO/KVC-friendly manner if you so wish, it's just a little more work: try the code below, then read Apple's NSKeyValueCoding Protocol Reference and their Key-Value Coding Programming Guide for an explanation:
// Instead of [_tradeArray addObject:newTrade];
[[self mutableArrayValueForKey:#"_tradeArray"] addObject:newTrade];

Trying to access a NSTextView from another class

I'm creating a NSTextView in my AppController.h:
#interface AppController : NSObject {
IBOutlet NSTextView *texto;
}
#property (assign) IBOutlet NSTextView *texto;
#end
After connected and properly checked, I'm trying to set a texto for this TextView from another class (AppMenu.m), but with no luck:
#import "AppController.h"
- (IBAction)setText:(id)sender {
AppController *appControl = [[AppController alloc] init];
[[appControl texto] setString:#"Hello"];
}
What should I do?
The problem is that Appmenu creates a new instance of texto, a local one just for appmenu (with the same properties), and not setting properties on the one actually in appcontroller. If you try debugging, you'll see that the two texto objects have different memory pointers.
You could make appcontroller the delegate for appmenu and create a 'setTextoProps' method which can pass data from appmenu over to appcontroller.
You could also make an instance of storyboard.appcontroller and set data directly with something like
Appcontroller *controller = [self.storyboard instantiateViewControllerWithIdentifi er:#"appcontroller"];
[self.controller.texto setText...];
When you call alloc you create a new object. What you need is a reference to the AppController that already exists.
(I'm assuming the text view is already displayed by an AppController object before you execute the code that tries to change its field.)

textView not getting set from another view controller (using Singleton class)

I have a textViewController class. I want to set(basically update) the corresponding textView's content from another view controller which I am pushing over the present textViewController. The way I thought I could do this was to have a shared singleton class and have a string property there to contain the text. I have been using the singleton for storing some other content as well and it worked fine till now.
But the text variable in singleton class doesn't hold the content I pass to it from the second view controller and hence the textViewController, after popping the second view controller, displays the old text even after reappearing. I am updating the textView in its viewWillAppear method which is getting called but shows old text content on NSLogging.
What am I missing here? Please suggest a solution, stuck at it for a long time now.
Declaration
Firstly, declare the NSString in your app delegate .h file. It should look something like this:
//YourAppDelegate.h
#import <UIKit/UIKit.h>
#interface YourAppDelegate : NSObject < UIApplicationDelegate >
{
NSString *sharedString; //WE ADDED THIS
}
#property (nonatomic, retain) NSString *sharedString; //AND THIS
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet SomeViewController *viewController;
#end
Now you want to synthesize the object so that the accessor and mutator methods are made for you. This means you don't have to write the setSharedString: and getSharedString methods - we can simply access and mutate the object by making a reference to it. This is how we synthesize it in the .m file:
//YourAppDelegate.m
#synthesize sharedString;
Assigning a Value
When you want to assign a value to sharedString from another class, you must first retrieve the active instance of your application delegate:
YourAppDelegate *appDelegate = (YourAppDelegate*)[[UIApplication sharedApplication] delegate];
The appDelegate object here is your running app delegate instance. To access the sharedString NSString object in the delegate and assign a value, we'd do this:
appDelegate.sharedString = #"some string we want to assign";
For the duration of our application's runtime, "some string we want to assign" is now stored in sharedString in our app delegate.
Retrieving the Value
You'll want to retrieve the value at some point. To do this, again we'll have to get the running instance of our application delegate:
YourAppDelegate *appDelegate = (YourAppDelegate*)[[UIApplication sharedApplication] delegate];
Once we have the running instance, we can then access the sharedString object stored inside it:
NSString *retrievedString = appDelegate.sharedString;
From this point, retrievedString now holds the value "some string we want to assign".
Note:
Everywhere I mention YourAppDelegate, I am referring to your app delegate - the app delegate you have in your project. It'll be related to your project name (look for the file).
How your NSString property for your Text-Variable is defined? Is it a "weak"?

How to generate a generic table view controller?

I've created a custom TablePickerViewController which is a subclass of UITableViewController. I'm using this class to display a list of object of a custom type TablePickerItem.
I'm using TablePickerViewController multiple times in my iOS application to show different kinds of lists where the user has to pick an item -- and then another view controller MainViewController should react on this selection and do something.
I've created this protocol and created a delegate property in the TablePickerViewController:
#protocol TablePickerViewControllerDelegate <NSObject>
- (void)tablePickerViewController:(TablePickerViewController *)controller
didSelectItem:(TablePickerItem*)item;
#end
When I setup a new TablePickerViewController in MainViewController it is also set as delegate -- than it will be notified when the user taps an cell in the table view.
The problem is that my MainViewController will setup multiple TablePickerViewController with different data (TablePickerItem). How should I setup my MainViewController to handle these multiple TablePickerViewController? Events from each of them will results in calling to the same protocol-method in my MainViewController.
Further I need to get the element which the TablePickerItem represents, as I need to know for instance the elements ID when acting in the tablePickerViewController:didSelectItem method. Should I just handle this by adding something like #property (nonatomic) id element to the TablePickerItem and set the original object into this property then creating it?
Maybe someone can give me an example on how to create an generic table view controller, if my solutions seems being done in the wrong way.
I'm not entirely sure of your set up, but if you have multiple pickers that feedback to the main controller then you could just have a reference to the picker e.g.
// MainViewController.m
#interface MainViewController ()
#property (nonatomic, strong) TablePickerViewController *picker1;
#property (nonatomic, strong) TablePickerViewController *picker2;
// ... and so on. Obviously you know your problem domain so you can change
// the terrible naming above to something appropriate
#end
#implementation MainViewController
// ...
- (void)theMethodWhereYouSetUpYourPickers;
{
TablePickerViewController *picker1 = [[TablePickerViewController alloc] init];
picker1.delegate = self;
self.picker1 = picker1;
// ...
}
- (void)tablePickerViewController:(TablePickerViewController *)controller
didSelectItem:(TablePickerItem*)item;
{
if (controller == self.picker1) {
NSLog(#"Something was picked in picker 1 %#", item);
} else if (controller == self.picker2) {
NSLog(#"Something was picked in picker 2 %#", item);
}
}
// ...
#end