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];
Related
So, I was wondering what the proper way to declare a global variable is in an iOS Project.
I don't want it set as a property, because the variable should not be accessible from outside the class.
I am going to provide a few ways I have seen, let me know which is the proper way, and if there is another way that is better.
This way I add the global variable inside curly braces after the #interface declaration in the implementation file .m. Then I can initialize the variable in the viewDidLoad
#import "ViewController.h"
#interface ViewController () {
int globalVariableTest;
}
#end
#implementation ViewController
Another way I add the global variable inside curly braces after the #implementation declaration in the implementation file .m. Again intializing in the viewDidLoad
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController {
int globalVariableTest;
}
Another way is adding the variable after the #implementation without the curly braces, also this allows me to set the intial value without the viewDidLoad
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
int globalVariableTest = 1;
Another way is to add the variable after the #interface inside the header file .h
#interface ViewController : UIViewController
{
int globalVariableTest;
}
So if there is a better way please let me know, all help will be appreciated!
Declaring variables inside curly braces is actually declaring an instance variable or "ivar" for short. That is, a variable that's local to instances of your class.
This used to only be possible after #interface declarations, which is why you sometimes see it there. This changed around Xcode 4 so that you can now do it after #implementation also. As far as I'm aware, this is just stylistic preference. ivars are never accessible outside a class (in theory. Technically, everything is accessible to everything in C), so defining them in the .h won't make them public. It does expose an implementation detail, though, which is why most code I see now that uses them puts them in the #implementation.
But I don't see them much in code anymore. Because when you define a #property what is actually happening under the covers is an ivar, a getter method, and a setter method are all actually being synthesized for you. The getter and setter methods just get the value of the ivar and set the value of the ivar, respectively.
So if what you want is something that has the same scope as a property, but doesn't come with the -myVar and -setMyVar: methods, then this is the right way to go.
But you probably shouldn't want that. There are a whole bunch of reasons that it's nice to only access ivars through accessor methods. It lets you override functionality, translate values, and all the other sorts of fun things abstraction affords you.
If what you want is a #property that isn't accessible outside the class, just declare it in a class extension:
//In MyClass.m
#interface MyClass()
#property NSNumber *myProperty;
#end
#implementation MyClass
//All your implementation stuff here.
#end
Because it's not in the .h file, it won't be "visible" to other classes (In theory. See above about everything being visible in C).
If on the other hand, what you really truly want is something that is really truly global (hint: you shouldn't. Global variables are generally a smell of bad design), you need to define it at the top of your file outside any #interface or #implementation blocks.
Another related tidbit: To define a "global" variable with a scope limited to a given file, look into C's static keyword. It's interesting.
You can use a singleton class to create/share (read / write) all variables across different classes (view controller).
.h
#interface SharedVariables : NSObject {
NSDictionary *dicti_StackSites;
NSDictionary *dicti_UserMe;
}
#property(nonatomic, strong) NSDictionary *dicti_StackSites;
#property(nonatomic, strong) NSDictionary *dicti_UserMe;
+(id)sharedVariablesManager;
#end
SharedVariables.m
#import "SharedVariables.h"
#implementation SharedVariables
#synthesize dicti_StackSites;
#synthesize dicti_UserMe;
+(id)sharedVariablesManager {
static SharedVariables *sharedVariablesClass = nil;
#synchronized(self) {
if (sharedVariablesClass == nil) {
sharedVariablesClass = [[self alloc] init];
}
}
return sharedVariablesClass;
}
-(id)init {
if (self = [super init]) {
dicti_StackSites = [[NSDictionary alloc] init];
dicti_UserMe = [[NSDictionary alloc] init];
}
return self;
}
-(void)dealloc {
}
#end
Usage from any other class
#import "SharedVariables.h"
SharedVariables *sharedManager = [SharedVariables sharedVariablesManager];
//to get sharedManager.dicti_StackSites
//to set sharedManager.dicti_StackSites = ...
another question i'm trying to use a setter within another class but I seem to get this odd error here is the code below:
AppDataSorting.h
#import <Foundation/Foundation.h>
#interface AppDataSorting : NSObject{
NSString *createNewFood;
NSNumber *createNewFoodCarbCount;
}
#property (readwrite) NSString *createNewFood;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
{
// Insert code here to initialize your application
}
- (IBAction)saveData:(id)sender {
NSLog(#"%#", self.foodName.stringValue);
self.createNewFood = self.foodName.stringValue;
NSLog(#"%.1f", self.carbAmount.floatValue);
}
#end
I get the error message in AppDelegate.m which is: Property 'createNewFood' not found on object of type 'AppDelegate *'
Could someone please explain the issue here?
You declare this property:
#property (readwrite) NSString *createNewFood;
In AppDataSorting.h so you can access it like self.createNewFood in AppDataSorting.m file not AppDelegate.m. If you want to call it as you do in AppDelegate.m you have move this line:
#property (readwrite) NSString *createNewFood;
to AppDelegate.h file.
Or if you want to use property from AppDataSorting class in AppDelegate you have to create object and call it on that object:
- (IBAction)saveData:(id)sender {
NSLog(#"%#", self.foodName.stringValue);
AppDataSorting *dSorting = [[AppDataSorting alloc] init];
dSorting.createNewFood = self.foodName.stringValue;
NSLog(#"%.1f", self.carbAmount.floatValue);
}
In -saveData:, self refers to an instance of NSAppDelegate. The createNewFood property is defined on instances of the class AppDataSorting.
Also note that Cocoa/CF naming conventions give special meaning to methods that start with "init", "new" and (to a lesser degree) "create". You probably want to avoid such things in your property names. Details here.
In general, properties should represent conceptual "properties" of an object. So if you had a Person class, it might have a name property, but it wouldn't have a createNewOutfit property.
You need to access createNewFood on an instance of AppDataSorting - but you're trying to access the property on the AppDelegate-class which clearly doesn't implement it.
So you would need to create an instance of AppDataSorting and then access the property like so:
AppDataSorting *instance = [[AppDataSorting alloc] init];
instance.createNewFood = self.foodName.stringValue;
Final notes:
The docs provide a good base of information
If you don't need atomicity you should always declare properties with the nonatomic attribute
createNewFood is not a good name for a property since it suggests a method which creates new food - yet it's only meant to store data (in this case an NSString instance)
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.)
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.
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"?