This is the properties declaration:
#property (atomic, weak) zooView* zooView;
This is my custom implementation:
__weak zooView* _zooView;
-(zooView*) getZooView
{
return _zooView;
}
-(void) setZooView:(btBasePinView*)inZooView
{
_zooView = inZooView;
}
I am accessing this property on another thread, on the same class:
[self.zooView imgLoadComplete:self.fullImg];
From some reason, when I access self.zooView I am returned with a nil object.
If I remove the custom setter \ getter, everything works fine.
What might be the reason?
Thanks
The getter for zooView should be -zooView not -getZooView.
To have an instance variable instead of a global, just synthesize it.
#synthesize zooView = _zooView;
-(zooView*) zooView
{
return _zooView;
}
-(void) setZooView:(btBasePinView*)inZooView
{
_zooView = inZooView;
}
This will define an ivar _zooView with your specified getter/setter.
Related
I have a UITableViewCell ProductsCell, I registered it in a nib , and dequeue to use it.
I want to set a property of it readonly. How to do it better?
Here is the code:
#property (nonatomic, strong, readonly) MyProductsVC * targetMyProductsVC;
- (MyProductsVC *)targetMyProductsVC{
if(!_targetMyProductsVC){
UIResponder *target = self.nextResponder;
do {
target = target.nextResponder;
} while (![target isKindOfClass: ZBMyProductsVC.self] && target != nil);
_targetMyProductsVC = (ZBMyProductsVC *)target;
}
return _targetMyProductsVC;
}
I can't put the implementation. in -init,-awakeFromNib , because I use UIResponder to find the parent ViewController.
Because in above methods, the cell seems like have not been added on the super view.
If I do like this ,
#property (nonatomic, strong, readonly) MyProductsVC * targetMyProductsVC;
Xcode reports:
Use of undeclared identifier '_targetMyProductsVC'
It is OK to set two property. one is inside like above , just set the other readonly property outside getter method (return the former property.)
It a little dirty ,
any better way ?
The code can work:
#property (nonatomic, strong, readonly) MyProductsVC * targetMyProductsVCReadOnly;
#property (nonatomic, strong) MyProductsVC * targetMyProductsVC;
- (MyProductsVC *)targetMyProductsVC{
if(!_targetMyProductsVC){
UIResponder *target = self.nextResponder;
do {
target = target.nextResponder;
} while (![target isKindOfClass: ZBMyProductsVC.self] && target != nil);
_targetMyProductsVC = (ZBMyProductsVC *)target;
}
return _targetMyProductsVC; }
- (MyProductsVC *)targetMyProductsVCReadOnly{
return self.targetMyProductsVC; }
Because you are implementing your own property getter for a readonly property, which means there is only one accessor (i.e. there is no setter), the compiler will not automatically declare the backing variable. From Encapsulating Data:
Note: The compiler will automatically synthesize an instance variable in all situations where it’s also synthesizing at least one accessor method. If you implement both a getter and a setter for a readwrite property, or a getter for a readonly property, the compiler will assume that you are taking control over the property implementation and won’t synthesize an instance variable automatically.
If you still need an instance variable, you’ll need to request that one be synthesized:
#synthesize property = _property;
You insert the above before your getter implementation to resolve the undeclared variable error.
HTH
I have the following protocol:
#protocol CardTransferFundsDelegate <NSObject>
#property (strong, nonatomic) id<CardTransferFundsView> view;
#end
I have the following in the .h file:
#interface CardTopViewModel : NSObject<CardTransferFundsDelegate>
- (instancetype)initWithVirtualCard:(Card *)card;
#end
In my .m I have the following:
#interface CardTopUpViewModel()
#property (strong, nonatomic) Card *card;
#end
#implementation CardTopUpViewModel
-(instancetype)initWithCard:(Card *)card {
self = [super init];
if(self){
self.card = card;
}
return self;
}
- (id <CardTransferFundsView>)view {
return nil;
}
- (void)setView:(id <CardTransferFundsView>)view {
self.view = view;
}
#end
The issue I have is whenever I call setView it then calls self.view which then calls the getter method and I have a program that just keeps running infinitely.
So my question is, How do I fix this issue, such that the protocol still keeps the property but I am able to get and set the view without having the program run infinitely?
You have implemented the setter, setView, in terms of itself, set.view, so it will recurse until the call stack overflows.
To implement the property specified in your protocol you need three things:
Storage - an instance variable in which to hold the properties value
A setter
A getter
First add an instance variable, say myView:
#implementation CardTopUpViewModel
{
id <CardTransferFundsView>) myView; // storage for view property
}
Now your setter becomes:
- (void)setView:(id <CardTransferFundsView>)view
{
myView = view;
}
And the getter is similarly trivial.
Or of course you can just skip all this and use a property declaration in your #interface which matches that in the protocol and the compiler will provide the storage, setter and getter automagically.
HTH
You should not call self.view = view will call the setter method again and again resulting infinite call. That moto is do not call setter method in with in setter method (setting property will call it again). So Issue in below lines. so view is already a property of viewcontroller. - (void) setView:(id)view is setter method for the view Property. try use another name.
Basically you should be very careful while creating method start with set. Usually try to use method name which starts with any verb as it does some action.
- (void)setView:(id <CardTransferFundsView>)view {
self.view = view;
}
create any property of id <CardTransferFundsView>) with other name and use with in setter method in place of self.view = view.
Is there a way to define a setter method that will run on setting a property like:
i want to call
object.something = 0;
meanwhile in object class i want to achieve something like
- (void)setSomething:(NSInteger)something{
self.something = something;
// some other work too
}
What you want is called property.
you define property in class #interface like:
#interface MyClass()
#property (strong, nonatomic) SomeClass *object;
#end
It will automatically create ivar _object, setter and getter for it.
You can override accessor methods. But if you override both setter and getter, you need to synthesize property like:
#implementation MyClass
#synthesize object = _object;
//setter
- (void)setObject:(SomeClass *)object
{
_object = object;
}
//getter
- (SomeClass *)object
{
return _object;
}
//class implementation
#end
You can do it like this:
#property (nonatomic, weak, setter = setSomething:) UIImageView *photoImageView;
Anyway, setSomething: is the default method for a property named something. You just need to replace self.something with _something, as pointed in the comments.
What is the best practice?
Declare the property as nonatomic
Create custom getter too
Another possibility that I'm not aware of
and why prefer one of this solution rather another.
In most of the cases, you just need to provide implementation for setter and declare the property as nonatmoic. This will generate ivar with underscore prefix and you need to set the value in setter method.
You don't normally need to override getter unless you have special logic in getter or the property need to be atomic.
If you do want to provide getter (along with setter), you may need a backend ivar either by declare it in #implementation{ /*here*/ } or use #synthesize to generate one.
In case for atomic property:
#interface MyClass : NSObject
#property (atomic) id object; // atomic is default attribute
#end
#implementation MyClass
#synthesize object = _object; // to create ivar
- (id)object {
#synchronized(self) { // or use lock / atomic compare-and-swap
return _object;
}
}
- (void)setObject:(id)obj {
#synchronized(self) { // or use lock / atomic compare-and-swap
_object = obj;
}
}
#end
I tried to assign a value to recordingStatus -
ie recordingStatus = 1
But it doesn't go into the setter which i want some custom code.. what's wrong with my code?
Thanks.
Pier.
In file.h
#property (strong, nonatomic) IBOutlet UILabel *recordingStatusText;
#property (nonatomic)int recordingStatus;
....
In file.m
/* -------------------- Property Setter and Getters ----------------------*/
#synthesize recordingStatus;
- (int) getRecordingStatus {
return recordingStatus;
}
- (void) setRecordingStatus:(int)status
{
[_recordingStatusText setText: #"Just testing!"];
recordingStatus = status;
}
To set and get your property, you should use self.property = newValue;.
OVERRIDING SETTERS AND GETTERS
For getters you don't need to write 'get' in the method signature. So, your getter method uses the wrong name. If you want to override it, the method should be
-(int) recordingStatus {
// Custom Getter Method
return _recordingStatus;
}
In the case of ints, Objective-c wants to see your setter and getter methods in the format of
-(void)setValue:(int)newValue;
-(int)value;
Can you show the code where you call the setter? I'm assuming you're accessing the ivar directly by doing something like this (assuming your ivar is named recordingStatus):
recordingStatus = 1
Instead try this:
self.recordingStatus = 1