Objective-C Passing a variable to another IBAction - objective-c

This works fine:
NSString *myVariable;
- (IBAction) doFirstAction {
myVariable = #"123456789";
}
- (IBAction) doSecondAction {
NSLog(#"%#",myVariable);
}
However, if I do this (substituting the #"123456789" for some code which returns the same value ie "123456789") I cannot access the value in doSecondAction.
NSString *myVariable;
- (IBAction) doFirstAction {
myVariable = [imageNode getAttributeName:#"value"];
}
- (IBAction) doSecondAction {
NSLog(#"%#",myVariable);
}
Any clue as to why I cant access myVariable outside of doFirstAction?

you need to retain it
myVariable = [[imageNode getAttributeName:#"value] retain];
see also

Another way of doing this would be to define an accessor method that does the retaining for you. Thus in your interface definition:
#property (retain) NSString *myVariable;
and later in your implementation:
#synthesize myVariable;
Now Xcode generates getter and setter methods for you that will handle the retain statement for you. However, you now need to use the dot notation, since the equals sign is not overridden, and your setter method is not called unless you do so:
self.myVariable = [imageNode getAttributeName:#"value"];

Related

Sending property as a reference param to a function in iOS?

I want to do something like this:
#property (nonatomic, retain) NSObject *obj1;
#property (nonatomic, retain) NSObject *obj2;
- (id)init {
if ((self = [super init])) {
[SomeClass someFuncWithParam1:*(self.obj1) param2:*(self.obj2)];
}
}
#implementation SomeClass
+ (void)someFuncWithParam1:(NSObject **)param1 param2:(NSObject **)param2 {
//init obj1;
...
//init obj2;
...
}
#end
I haven't found any example how to pass objective-C properties into a function for initialization. I know that it is possible with usual variables but there are no examples about what to do with properties.
You cannot pass an argument by reference in (Objective-)C. What you probably mean is to
pass the address of a variable as an argument to the method, so that the method can
set the value of the variable via the pointer.
However, this does not work with properties.
self.obj1 is just a convenient notation for the method call [self obj1], which returns
the value of the property. And taking the address of a return value is not possible.
What you can do is
Pass the address of the corresponding instance variables:
[SomeClass someFuncWithParam1:&_obj1 param2:&_obj2];
The disadvantage is that the property accessor methods are bypassed. That may or may not be
relevant in your case.
Pass the address of temporary local variables:
NSObject *tmpObj1;
NSObject *tmpObj2;
[SomeClass someFuncWithParam1:&tmpObj1 param2:&tmpObj2];
self.obj1 = tmpObj1;
self.obj2 = tmpObj2;
Both solutions are not very nice. Alternatively, you could pass the entire object (self) to the helper method, which then initializes both properties.
Or you define a custom class with just the properties obj1 and obj2, and make the helper method return an instance of this custom class.

Get pointer to array held in super class

Studying polymorphism in objective c . I'm trying to do some things using an NSMutableArray that is held by my super class, so I need a pointer to it from the sub class.
SuperViewController.h
#interface SuperViewController : UIViewController
- (NSMutableArray *) myArray;
#end
SuperViewController.m
#interface SuperViewController()
#property (strong, nonatomic) NSMutableArray *myArray;
#end
#implementation SuperViewController
- (NSMutableArray *) myArray {return self.myArray;}
#end
Then, in my subclass, I have this:
SubViewController.h
#import SuperViewController.h
#interface SubViewController : SuperViewController
- (void) updateUI;
#end
SubViewController.m
#implementation
- (void) updateUI
{
(NSMutableArray *) myArray = [super myArray];
}
#end
It crashes the App . I've tried quite a few different approaches, but I always wind up crashing. Can anyone help me out? Thanks!
The reason is, that you have a recursion which blows the stack:
- (NSMutableArray *) myArray
{
return self.myArray;
}
This method calls itself. The dot notation is a short form of method invocation:
- (NSMutableArray *) myArray
{
return [self myArray];
}
It is not an access to the object's context (ivar) as you probably expected:
- (NSMutableArray *) myArray
{
return self->_myArray;
}
The right way is to use the ivar directly:
- (NSMutableArray *) myArray
{
return _myArray;
}
BTW:
Properties can have the readonly attribute.
Using super in the derived class is useless and dangerous. It does not use the super's context (which does not exist, because every instance object has only one context built from the whole class hierarchy), but uses the super implementation of the method. You did not overwrite this implementation in the derived class. self would work, too, and gives you the ability to overwrite the getter.
You've written self.myArray to access an instance variable. The dot notation is a property access, and will invoke a property-like method even if not declared as a property. In your case this means your attempt to access the instance variable is in fact a self-recursive call, which will result in stack overflow.
To access an instance variable either use just it's name or the -> member access operator, e.g. _myArray or self->_myArray.

Objective-C generic getter methods

I need to overwrite the getter method of multiple properties using the getter attribute when I declare my property like the following. I would like the getter of all my properties to be the same method as the code to get those three properties is the same.
#property (nonatomic,strong, getter=getObject) (NSString*) obj1;
#property (nonatomic,strong, getter=getObject) (NSString*) obj2;
#property (nonatomic,strong, getter=getObject) (NSString*) obj3;
Although, I would need, in my getObject method, to know which property is currently being asked. Is is possible in the implementation of the getObject method to know which object is currently being asked? I would like the following %# code to return either obj1, obj2 or obj3.
-(NSString*) getObject{
NSLog(#"the property requested is: %#", ?????)
}
Any ideas on how to do that?
Thanks a lot!
Renaud
This is not possible.
When you define your getter method, the compiler is going to translate requests to myObject.obj3 into simply [myObject getObject]. At that point, you have lost the information about which property was invoked.
You should just define a different getter for each property, and any shared or duplicated code can go into a private method like getObject::
- (NSString *)getObject:(NSString *)propertyName {
// ...
}
- (NSString *)obj1 {
return [self getObject:#"obj1"];
}
- (NSString *)obj2 {
return [self getObject:#"obj2"];
}
// ...

#property and setters and getters

If I create a #property and synthesize it, and create a getter and setter as well like so:
#import <UIKit/UIKit.h>
{
NSString * property;
}
#property NSString * property;
--------------------------------
#implementation
#synthesize property = _property
-(void)setProperty(NSString *) property
{
_property = property;
}
-(NSString *)property
{
return _property = #"something";
}
Am I correct in assuming that this call
-(NSString *)returnValue
{
return self.property; // I know that this automatically calls the built in getter function that comes with synthesizing a property, but am I correct in assuming that I have overridden the getter with my getter? Or must I explicitly call my self-defined getter?
}
is the same as this call?
-(NSString *)returnValue
{
return property; // does this call the getter function or the instance variable?
}
is the same as this call?
-(NSString *)returnValue
{
return _property; // is this the same as the first example above?
}
There are a number of problems with your code, not least of which is that you've inadvertently defined two different instance variables: property and _property.
Objective-C property syntax is merely shorthand for plain old methods and instance variables. You should start by implementing your example without properties: just use regular instance variables and methods:
#interface MyClass {
NSString* _myProperty;
}
- (NSString*)myProperty;
- (void)setMyProperty:(NSString*)value;
- (NSString*)someOtherMethod;
#end
#implementation MyClass
- (NSString*)myProperty {
return [_myProperty stringByAppendingString:#" Tricky."];
}
- (void)setMyProperty:(NSString*)value {
_myProperty = value; // Assuming ARC is enabled.
}
- (NSString*)someOtherMethod {
return [self myProperty];
}
#end
To convert this code to use properties, you merely replace the myProperty method declarations with a property declaration.
#interface MyClass {
NSString* _myProperty;
}
#property (nonatomic, retain) NSString* myProperty
- (NSString*)someOtherMethod;
#end
...
The implementation remains the same, and works the same.
You have the option of synthesizing your property in your implementation, and this allows you to remove the _myProperty instance variable declaration, and the generic property setter:
#interface MyClass
#property (nonatomic, retain) NSString* myProperty;
- (NSString*)someOtherMethod;
#end
#implementation MyClass
#synthesize myProperty = _myProperty; // setter and ivar are created automatically
- (NSString*)myProperty {
return [_myProperty stringByAppendingString:#" Tricky."];
}
- (NSString*)someOtherMethod {
return [self myProperty];
}
Each of these examples are identical in how they operate, the property syntax merely shorthand that allows you to write less actual code.
return self.property – will call your overridden getter.
return _property; – accesses the property's instance variable directly, no call to the getter.
return property; – instance variable.
EDIT: I should emphasize that you will have two different NSString variables -- property and _property. I'm assuming you're testing the boundaries here and not providing actual production code.
above answer elaborate almost all the thing , i want to elaborate it little more.
// older way
#interface MyClass {
NSString* _myProperty; // instance variable
}
- (NSString*)myProperty; // getter method
- (void)setMyProperty:(NSString*)value;//setter method
#end
the instance variable can not be seen outside this class , for that we have to make getter and setter for it.
and latter on synthesis it in .m file
but now
we only used
#property(nonatomic) NSString *myProperty;
the #property is an Objective-C directive which declares the property
-> The "`nonatomic`" in the parenthesis specifies that the property is non-atomic in nature.
-> and then we define the type and name of our property.
-> prototyping of getter and setter method
now go to .m file
previously we have synthesis this property by using #synthesis , now it also not required it automatically done by IDE.
little addition : this `#synthesis` now generate the getter and setter(if not readonly) methods.

Objective-C: Custom BOOL accessor (getter & setter) methods

I know someone already asked about Writing getter and setter for BOOL variable. But, if I'm defining a custom getter & setter methods setImmediate & isImmediate, respectively, I'd like passcode.immediate = NO to work too.
I do not have any instance variables, but maybe I should? I could add one for NSDate *lastUnlocked.
Here's the relevant code so far:
// PasscodeLock.h
extern NSString *const kPasscodeLastUnlocked;
#interface PasscodeLock : NSObject {
}
- (BOOL)isImmediate;
- (void)setImmediate:(BOOL)on;
- (NSDate *)lastUnlocked;
- (void)resetLastUnlocked;
- (void)setLastUnlocked:(NSDate *)lastUnlocked;
#end
// PasscodeLock.m
#import "PasscodeLock.h"
NSString *const kPasscodeLastUnlocked = #"kPasscodeLastUnlocked";
#implementation PasscodeLock
#pragma mark PasscodeLock
- (BOOL)isImmediate {
return self.lastUnlocked == nil;
}
- (void)setImmediate:(BOOL)on {
if (on) {
[self resetLastUnlocked];
} else {
self.lastUnlocked = nil;
}
}
- (NSDate *)lastUnlocked {
return [[NSUserDefaults standardUserDefaults] objectForKey:kPasscodeLastUnlocked];
}
- (void)resetLastUnlocked {
NSDate *now = [[NSDate alloc] init];
self.lastUnlocked = now;
[now release];
}
- (void)setLastUnlocked:(NSDate *)lastUnlocked {
[[NSUserDefaults standardUserDefaults] setObject:lastUnlocked forKey:kPasscodeLastUnlocked];
}
Then, in a view controller that has PasswordLock *passwordLock as an instance variable, I want to do passcode.immediate = NO, but I get the error "Property 'immediate' not found on object of type 'PasscodeLock *'."
How do I get passcode.immediate = NO to work?
You need something like
#property (nonatomic, getter=isImmediate) BOOL immediate;
in your .h file and of course a #synthesize statement in your .m file. This creates the property AND defines your getter method name.
Declare such property in the #interface:
#interface PasscodeLock : NSObject {
}
#property(dynamic, getter=isImmediate,
setter=setImmediate:) BOOL immediate;
// etc.
#end
(The setter= part is optional)
I think the issue ids that your getter and setter names are not consistent. By default, if you have
foo.immediate
in your code, it is assumed that the getter and setter are named -immediate and -setImmediate: respectively. Your getter is not named correctly. The best way around this is to declare a property as Mark and Kenny have already said but you could also change the name of your getter.
The point is that you do not need declared properties to use dot syntax, but if you are going to use dot syntax then declared properties are the recommended way of declaring the getter and setter.