I just started programming in XCode and I need your help.
I have two voids; in the first void I create a NSString, and in the second void I need the value of that string, but i don't know how to obtain that value.
This is a shortend version of my .h file
//.h file
-(void)viewDidLoad
{
[self ActionOne];
}
-(IBAction)ButtonClick (id):sender
{
[self ActionTwo];
}
-(void)ActionOne
{
NSString *VarString = #"hello";
}
-(void)ActionTwo
{
NSLog (#"%#", VarString);
}
My problem is that NSLog's output is 'null', I hope someone can help me
You have declared a local variable in ActionOne. It only lives as long as the method is running. For persistent storage, you need an ivar (that's a term used in Objective-C to mean an "instance variable", which is a variable for which there is a separate copy for each object that is an instance of a class). The easiest way to do this is to declare a property, which will create an ivar and methods to access it for reading and writing. In your .h file:
#interface MyViewController: UIViewController
#property (nonatomic, strong) NSString *varString;
// ... method declarations, etc
#end
And then in your .m file:
-(void)actionOne
{
self.varString = #"hello";
}
-(void)actionTwo
{
NSLog(#"%#", self.varString);
}
Related
In Objective c, what is the differences between instance variables var1 and var2 showing below?
(This code is in one .m file, does it make any difference if the #interface is in a header file & #implementation is in implementation file? I mean any difference comparing with that in one file regarding to the two instance variables.)
#interface MyService {
NSString *var1;
}
#end
#implementation MyService {
NSString *var2;
}
#end
The difference between them is visibility. The variable defined in the #interface section is visible to any code which imports the interface. The variable declared in the #implementation section is only visible to code within the class implementation.
If the #interface is declared in the implementation file, it will act, for all practical purposes, the same as declaring it in the #implementation section.
Instance variables declared in the implementation are implicitly
hidden (effectively private) and the visibility cannot be changed -
#public, #protected and #private do not produce compiler errors (with
the current Clang at least) but are ignored.
you can found it here
I have deep searched for your question.Well asked Leem.fin brother.I tried sample one
#import "SecondViewController.h"
#interface SecondViewController ()
{
NSString *variableOne;
}
#end
#implementation SecondViewController
{
NSString *variableTwo;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self setValueToString];
NSLog(#"The variable One is - %#",variableOne);
NSLog(#"The variable Two is - %#",variableTwo);
}
-(void)setValueToString
{
variableOne = #"iOS";
variableTwo = #"iPhone";
}
The printed results are
The variable One is - iOS
The variable Two is - iPhone
But when I tried to access these in Class method
+(void)changeStrings
{
variableOne = #"iPad"; //I get error here
variableTwo = #"iMac"; //I get error here
}
The error shows
Instance variable 'variableOne' accessed in class method
Instance variable 'variableTwo' accessed in class method
From above code I understood
Both are instance variables
That can be accessed only in instance methods
There is no difference between them
So Where to put
Difference between them
Difference between putting variable inside interface and implementation
I am trying to do very simple operation.
in "TestFile.h" file i've declare property:
#property (nonatomic) NSDictionary *justTest;
and in implementation file "TestFile.m":
-(NSDictionary *)justTest:(NSString *) mystring {
NSLog(#"Here is my string: %#", mystring);
return nil;
}
Now i am trying to call "justTest" from another file. What i am doing:
#import "TestFile.h"
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
NSDictionary *testFile = [[TestFile alloc] init];
[testFile justTest:#"Hello World!"]
}
This works fine until i'm trying to pass parameter.
if i just execute
[testFile justTest];
it works, but when i try to pass parameter
[testFile justTest:#"Hello World!"];
does not work and the debug message is:
no visible #interface for 'TestFile' declares the selector 'justTest':
What is wrong with me?
You need to make this method public by adding method name to TestFile.h file before #end:
-(NSDictionary *)justTest:(NSString *) mystring;
Just to let you know when you add #property compiler synthesise it (create) two method getter, exactly the same name as your property and setter compiler add 'set' prefix, for example, you declare:
#property (nonatomic) NSDictionary *justTest;
compiler will create two methods:
-(NSDictionary *)justTest {...}
-(void)setJustTest {...}
You need to know that in your code you override the getter method.
Declare your method in TestFile.h file before calling from an external class.
-(NSDictionary *)justTest:(NSString *) mystring;
I got this global variable
define AN_MOBILE_HOSTNAME #"(hostname).mob"
And I want to change the hostname with a segmented control variable, that defines different regions (Europe-USA-Australia)
Thanks
Sorry for my ignorance, im a begginer
You can't change Pre-Processor macros after compile time. You are going to need to set a global NSString for what you want accomplished.
.h
extern NSString *AN_MOBILE_HOSTNAME;
#interface SomeClass
{
}
#end
.m
NSString *AN_MOBILE_HOSTNAME;
#implementation SomeClass
-(id)init
{
//Do the if(self) stuff
{
AN_MOBILE_HOSTNAME = #"(hostname).mob";
}
}
-(void)FunctionToChangeStuff:(NSString*)somethingElse
{
AN_MOBILE_HOSTNAME = somethingElse;
}
#end
Or you could make the object a class variable if you have a singleton class that your program knows about.
Problem
I want to create an interface with this signature, but without auto-synthesized instance variables:
#interface MyObject : NSObject
#property (nonatomic, copy) NSArray *values;
#end
Question:
Is it possible to prevent instance variable to be auto synthesized in .m #implementaion, as I want to implement my own getter and setter and I'm not going to use instance variable.
Reason:
The reason is that I don't want to have memory overhead, as data is going to be stored in plain bytes archive. At the same time I don't want users to know implementation issues and keep interface signature unchanged.
#implementation MyObject {
NSData *_data
{
- (NSArray *)values
{
// Generate NSArray from _data
}
- (void)setValues(NSArray *)values
{
// Set _data from values
}
#pragma mark - Hidden init
- (id)initWithData:(NSData *)data
{
// Set _data
}
#end
If you implement both getter and setter yourself, instance variables are not synthesized.
As others said - if you override the setter and getter - the compiler does't do anything else. So what you want.. is what you have typed out.
If you dont wantbto create just create only instance variable.
#interface MyObject : NSObjet
{
NSArray *values;
}
#end
Trying to extend the capabilities from a open source project, I wrote a category for add a new method. In this new method, the category needs to access to an internal method from the original class, but the compiler says that it can't find the method (of course, is internal). Is there any way to expose this method for the category?
EDIT
I don't want to modify the original code, so I don't want to declare the internal method in the original class header file.
The code
In the original class implementation file (.m), I have this method implementation:
+(NSDictionary*) storeKitItems
{
return [NSDictionary dictionaryWithContentsOfFile:
[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:
#"MKStoreKitConfigs.plist"]];
}
In the category, I want to add this method:
- (void)requestProductData:(NSArray *(^)())loadIdentifierBlock
{
NSMutableArray *productsArray = [NSMutableArray array];
NSArray *consumables = [[[MKStoreManager storeKitItems] objectForKey:#"Consumables"] allKeys];
NSArray *nonConsumables = [[MKStoreManager storeKitItems] objectForKey:#"Non-Consumables"];
NSArray *subscriptions = [[[MKStoreManager storeKitItems] objectForKey:#"Subscriptions"] allKeys];
if(loadIdentifierBlock != nil) [productsArray addObjectsFromArray:loadIdentifierBlock()];
[productsArray addObjectsFromArray:consumables];
[productsArray addObjectsFromArray:nonConsumables];
[productsArray addObjectsFromArray:subscriptions];
self.productsRequest.delegate = self;
[self.productsRequest start];
}
In every line in which I call storeKitItemscompiler says: Class method "+storeKitItems" not found ...
This is trivial, make a forward declaration of the method.
Unfortunately, in obj-c, every method declaration must be inside #interface, so you can make it work in your category .m file with another internal category, e.g.
#interface MKStoreManager (CategoryInternal)
+ (NSDictionary*)storeKitItems;
#end
No implementation is needed, this only tells the compiler the method is somewhere else, similarly to #dynamic with properties.
If you are only interested in removing the warning, you can also just cast the class to id, the following should work, too:
NSDictionary* dictionary = [(id) [MKStoreManager class] storeKitItems];
However, my favorite solution is to do it a bit differently, let's assume the following example:
#interface MyClass
#end
#implementation MyClass
-(void)internalMethod {
}
#end
#interface MyClass (SomeFunctionality)
#end
#implementation MyClass (SomeFunctionality)
-(void)someMethod {
//WARNING HERE!
[self internalMethod];
}
#end
My solution is to split the class into two parts:
#interface MyClass
#end
#implementation MyClass
#end
#interface MyClass (Internal)
-(void)internalMethod;
#end
#implementation MyClass (Internal)
-(void)internalMethod {
}
#end
And include MyClass+Internal.h from both MyClass.m and MyClass+SomeFunctionality.m
A category has no access to the private methods of a class. It's no different than trying to call those methods from any other class. At least if you call the private method directly. Since Objective-C is so dynamic, you can call private methods (which is a bad idea) using other means such as using performSelector or with NSInvocation.
Again, this is a bad idea. An update to the implementation of the class could break your category.
Edit: Now that there is code posted -
Since the +storeKitItems method is not declared in the .h file, no category or other class can access the private method.
In you category implementation file you can define and informal protocol for the method
#interface YourClasses (ExternalMethods)
+(NSDictionary*) storeKitItems;
#end
This will stop the compiler from complaining about not knowing of the method storeKitItems in you category.