In my .h interface:
#property (nonatomic, strong) UIView *myView;
In my .m:
- (void)setMyView:(UIView *)aView {
_myView = aView; //Use of undeclared identifier "_myView"
}
Why the error?
I'm guessing that in addition to your explicit "setter" method, you also wrote your own explicit "getter" method for the myView property.
When you provide both of the "setter" and "getter" methods for a property, the compiler does not automatically generate an ivar for you. This makes sense since it is possible your property implementation doesn't make use of an ivar.
In this case you must declare your own ivar. Simply do this in the .m:
#implementation MyClass {
UIView *_myView;
}
With that you can reference the _myView ivar in your "setter" and "getter" methods.
Another possibility is that the property was declared in a parent class and you are overriding the "setter" method of the property. In this case you have no access to the ivar. You need to do this:
- (void)setMyView:(UIView *)aView {
[super setMyView:aView];
// do other stuff here
}
add second view as a subview:
[self.view addSubview:anotherView];
Just declaring a property myView in the header file does not create an instance variable called _myView. What you need to add is the following above the #implementation:
#interface ClassName ()
{
UIView *_myView;
}
This is a class extension that allows you to add instance variables and properties without letting other classes know. Then, if you don't already have it, add a synthesize line below the #implementation:
#synthesize myView = _myView;
The synthesize command creates getter and setter methods linked to the _myView instance variable. This also allows you to implement a custom setter without having to implement the getter method.
Hope this helps!
Related
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.
I currently have this init method for my superclass:
- (id)initWithFoo:(int)foo;
In a subclass, I have a custom init method that calls its superclass's init, like this. Bar is exclusive to the subclass.
-(id)initWithFoo:(int)foo Bar:(int)bar {
if (self = [super initWithFoo:foo]){
_bar = bar;
}
return self;
}
I run into problems when I create an instance of the subclass, because the compiler happily suggests the superclass init method in the list of possible initialization methods for my subclass instance, which I definitely do not want.
However, if I remove initWithFoo:(int)foo from the superclass's .h file then the subclasses can no longer use it within their own init methods.
Is there any way around this?
Yes, you can implement initWithFoo in your superclass and in your child make an "extension" declaration:
#interface SuperClass()
- (instancetype)initWithFoo:(int)foo;
#end
Make sure to place that declaration above #implementation in the .m file of your child
I am attempting to create an abstract class and inherit some of its properties in a subclass. If I leave the properties in the abstract class' header file, all of the properties are accessible. The problem is that the instance of the subclass can also access those properties, which is not always desirable in my case.
For instance, I have a delegate in my abstract class that sends down button presses to its sub class. I realize that this may not be the best way of structuring inheritance, so other suggestions are welcome. However, I would still like to know how my subclass can inherit some properties from its superclass without making all of those properties available in its instance. Thanks in advance!
Here is some example code below:
#interface AbstractClass : UIView
#property (nonatomic, strong) id<ButtonDelegate>buttonDelegate;
#end
…
#protocol ButtonDelegate
#required
- (void) buttonWasPressed;
#end
…
#interface SubClass() <ButtonDelegate>
- (id)init {
self = [super init];
if (self) {
self.buttonDelegate = self;
}
return self;
}
-(void) buttonWasPressed {
[self doSomething];
}
…
#implementation ViewController
- (void)viewDidLoad {
SubClass *subClass = [[SubClass alloc] init];
subClass.buttonDelegate = self; // THIS IS NOT DESIRABLE
}
Do like UIGestureRecognizer does.
All public properties and methods goes into UIGestureRecognizer.h
All protected properties and methods goes into UIGestureRecognizerSubclass.h.
Only import this in the *.m-files. Never include it in any public header.
All private properties and methods goes into *.m-files. Use the #interface ClassName ()
Example https://gist.github.com/hfossli/8041396
how to my subclass can inherit some properties from its superclass
without making all of those properties available in its instance
What is the problem with this?
#import <Foundation/Foundation.h>
#interface Animal : NSObject
{
#protected
NSString *name; // default access. Only visible to subclasses.
}
#end
#implementation Animal
-(NSString*)description {
return name;
}
#end
#interface Cow : Animal
#end
#implementation Cow
-(id)init {
self=[super init];
if (self){
name = #"cow";
}
return self;
}
#end
int main(int argc, char *argv[]) {
#autoreleasepool {
Cow *cow = [Cow new];
NSLog(#"%#", cow); // prints the name through internal access
// error accessing from the outside: NSLog(#"%#", cow.name);
Animal *animal = [Animal new];
// error accessing from the outside: NSLog(#"%#", animal.name);
}
}
Maybe I misunderstood the question, you say
Creating properties only visible to subclass in Objective-C
and then
The problem is that the instance of the subclass can also access those
properties
Which one is it?
Create an empty category on top of your implementation file (.m):
#interface AbstractClass()
#property (nonatomic, strong) id<ButtonDelegate>buttonDelegate;
#end
In that way, your subclass will inherit and can access that property, but not other external classes because it's not in the header.
I don't think there is any way to achieve this using property declaration.
Either a property be visible for all (declared in .h file) or it will be invisible for all (declared in .m file using category)
I guess one way is declaring public/protected variable in .h file class declaration:
#interface AbstractClass : UIView {
...
id<ButtonDelegate>buttonDelegate;
...
}
#end
I am not sure about this, but give a try.
I see one approach that can fit your problem, however, it is pretty rude. Use Antonio's suggestion and create the private category with the property. As you've mentioned, it's scope is limited to the .m file. So you can put your subclasses into that file. This will be hard to read the code if subclasses are huge, but this is the only way for you as far as I understand.
EDIT: well, I have another solution. Copy
#property (nonatomic, strong) id<ButtonDelegate>buttonDelegate;
to all your subclasses. This will give you a warning about the absence of the property's #synthesize, but should work. I'd prefer this, if subclasses wont be changed or added often.
Let me describe how it would work.
We add a property into the Abstract class, and it is hidden for all (even for subclasses):
// .m file
#interface Abstract ()
#property (nonatomic, strong) id<ButtonDelegate> buttonDelegate;
#end
#implementation Abstract
#synthsize buttonDelegate;
#end;
But due to runtime features of Objective-C we still can call for that property, and there will not be any runtime error, only compiler warning.
To get rid of that warning and to add an ability to autocomplete, we add property without #synthsize into all subclasses:
#interface MySubclass : Abstract
#property (nonatomic, strong) id<ButtonDelegate> buttonDelegate;
#end
This will tell the compiler that there is such a property somewhere. There will be also one warning about the absence of #synthesize, but Xcode will still could autocomplete if you write something like
MySubclass *subclass = ...
subclass.butto...
It can not be done. There is no private or protected in objective-c. Stuff declared in the .m file "private" interface is only visible to that class and not in any subclass. Also you can always use your "private" properties/methods from outside if you want, although it would be bad practice to do so.
I've defined a protocol for my custom class, and now I want to give it a delegate. The class will not be instantiated, only used for its class methods. The delegate class, however, has been instantiated and assigned to a constant. If I was instantiating the class, I would let it refer to its delegate like this:
#property (weak) MyDelegateClass <MyProtocol> *delegate;
But because I'm not instantiating the class, I can't give it properties. So how do I refer to its delegate? A getter method? Something like this? Do I also need to define a setter?
+ (<MyProtocol>MyDelegateClass *)delegate;
What's the syntax here?
#interface NeverInstanciatedClass
+ (MyDelegateClass *) delegate;
+ setDelegate: (MyDelegateClass* <MyProtocol>) delegate;
#end
#implementation
static MyDelegateClass <MyProtocol> *_delegate;
+ (MyDelegateClass *) delegate {
return _delegate;
}
+ setDelegate: (MyDelegateClass* <MyProtocol>) delegate {
_delegate = delegate;
}
#end
(from scratch - never compiled nor syntax checked)
If you don't ARC then you may want to add some memory management. But as you use (weak) I assume you use ARC.
If you use protocols at all then you do not need to fully qualify MyDelegateClass* <MyProtocol> . id <MyProtoco> should do. I just did that because you did it in your sniplets.
As you access methods (and you should then access methods only) that are declared in the protocol, there is no need to even know what type of object it is. All you (and the compiler) need to know is that it implements the protocol.
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