Considering the following case:
#interface Superclass : NSObject
...
#end
#interface Superclass
+ (void)methodToOverride
{
NSLog(#"This method should be overridden by subclass!");
}
+ (void)callMethodToOverride
{
[self methodToOverride];
}
#end
#interface SubClass : SuperClass
...
#end
#implementation SubClass
+ (void)methodToOverride
{
NSLog(#"I'm overriding this method!");
}
#end
Now, when calling
[Subclass callMethodToOverride];
I get "This method should be overridden by subclass!". Is it possible to get I'm overriding this method! instead or is this not possible with ObjC's static methods?
Cheers!
I use this paradigm from time to time and it works for me. In my implementations, I'm referencing [self class] instead of self. Maybe that's the key you're missing.
+ (void)callMethodToOverride
{
[[self class] methodToOverride];
NSLog(#"This is the class that I just used: %#", NSStringFromClass(self));
}
Sounds like it could just be a typo where you're not using the class you think you are.
Related
#interface SomeClass
- (void)funcA;
+ (void)funcB;
#end
#interface Test
#property(nonatomic, assign) Class aClass;
#end
#implementation Test
- (void) test {
// that's ok
[[aClass new] funcA];
// but how to call class method?
[aClass funcB] ?
}
#end
XCode note "Instance method 'function' is being used on 'Class' which is not in the root class"
Have you tried ?
[[aClass class] performSelector:#selector(funcB)];
[((id)aClass) funcB];
or similarly to #Pancho's answer
[[aClass class] funcB];
I have class ImageViewController. It has delegate:
#protocol ImageViewControllerDelegate
#optional
- (void)singleTapGestureRecognizer:(UITapGestureRecognizer *)gesture;
- (void)imageDidLoaded;
I also have class AttachmentViewController that subclass of ImageViewController. In that class I want to get event then image property in changed. So here is my code of it change:
- (void)setImage:(UIImage *)image
{
// * Assign image with animation
[UIView transitionWithView:self.imageView
duration:k_DURATION_imageAppearence
options:UIViewAnimationOptionTransitionCrossDissolve
animations: ^{
self.imageView.alpha = 1;
} completion:^(BOOL finished) {
if ([self respondsToSelector:#selector(imageDidLoaded)]) {
[self.delegate imageDidLoaded];
}
}];
But I can not use
if ([self.DELEGATE respondsToSelector:#selector(imageDidLoaded)])
Then I do it I have error:
No known instance method for selector 'respondsToSelector:'
Why? And how here I need to use this capabilities? Is my implementation ok? Or how can I get this notification?
I think that here will be ok to create clear methods in superclass and override it in subclass if it needs to implement is. Is it best way?
You should declare your protocol as #protocol ImageViewControllerDelegate <NSObject>
This says that any object that conforms to your protocol will also conform to the NSObject protocol that respondsToSelector: is declared in.
There's really not enough code here to understand what you're trying to do. Generally to setup a delegate you have a weak property on your class that represents the delegate, and a parent to that class's instance would set the delegate.
Here's some pseudo code:
#protocol SomeDelegateProtocol<NSObject>
- (void)someMethod:(id)someObject;
#end
#interface SomeClass:NSObject
#property (nonatomic, weak) id<SomeDelegateProtocol>delegate;
#end
#implementation SomeClass
- (void)someFunction {
if ([self.delegate respondsToSelector:#selector(someMethod:)]) {
// do code stuff
}
}
#end
///////////
#implementation SomeParentClass
- (void)someOtherFunction {
SomeClass *instance = [SomeClass new];
instance.delegate = self; // assuming self implements SomeDelegateProtocol, otherwise you get a warning
}
Hope this helps!
I want create a class that can inherit from two custom class.
Do you have any idea to do this please?
Please see below my example:
first class:
#interface UIZoomableView : UIView
{
UITapGestureRecognizer *_tapGestureRecognizer;
}
and implementation:
- (void)onDoubleTap:(UITapGestureRecognizer *)sender
{
CGSize newSize;
CGPoint centerPoint = self.center;
if ([self isSmall])
{
newSize = [self bigSize];
}
else
{
newSize = [self smallSize];
}
[UIView animateWithDuration:0.3 animations:^{
self.size = newSize;
self.center = centerPoint;
}];
}
Second class:
#interface UIDraggableView : UIView
UIPanGestureRecognizer *_panGestureRecognizer;
#end
implementation:
- (void)handlePan:(UIPanGestureRecognizer*)sender
{
..
}
i want to create a custom view that can be zoomable and draggable.
Do you have any idea to do this please? (without copy code..)
I think something like protocols but i want default value for the base classes?
How can i implement this using protocol or something like protocols.
Thanks for any response!
Objective-C doesn't support multiple inheritance. You could use a protocol, composition and message forwarding to achieve the same result.
A protocol defines a set of methods that an object must implement (it's possible to have optional methods too). Composition is basically the technique of include a reference to another object and calling that object when it's functionality is required. Message forwarding is a mechanism that allows objects to pass messages onto other objects, for example, an object that is included via composition.
Apple Reference:
Protocols
Composition
Message Forwarding (and specifically Forwarding and Multiple Inheritance)
So, in your case Composition might be a solution, below is the example code
#interface ClassA : NSObject {
}
-(void)methodA;
#end
#interface ClassB : NSObject {
}
-(void)methodB;
#end
#interface MyClass : NSObject {
ClassA *a;
ClassB *b;
}
-(id)initWithA:(ClassA *)anA b:(ClassB *)aB;
-(void)methodA;
-(void)methodB;
#end
#implementation MyClass
-(id)initWithA:(ClassA *)anA b:(ClassB *)aB {
a = anA ;
b = aB ;
}
-(void)methodA {
[a methodA] ;
}
-(void)methodB {
[b methodB] ;
}
#end
If you don't want to implement all the methods from ClassA and ClassB in MyClass, you can use Message Forwarding in MyClass to handle all the method invocations. Below works fine as long as ClassA and ClassB do not have any common methods.
#implementation MyClass
-(id)initWithA:(ClassA *)anA b:(ClassB *)aB {
a = anA ;
b = aB ;
}
//This method will be called, when MyClass can not handle the method itself
-(void)forwardInvocation:(NSInvocation *)anInvocation
{
if ([a respondsToSelector:[anInvocation selector]])
[a invokeWithTarget:someOtherObject];
else if ([b respondsToSelector:[anInvocation selector]])
[b invokeWithTarget:someOtherObject];
else
[super forwardInvocation:anInvocation];
}
#end
The closest that you can get to multiple inheritance in Objective C is with categories. These are a mechanism for adding additional methods to a class that already exists.
Note that this has some important limitations:
You can't add properties or ivars using a category, though you can use associated objects to get a similar effect;
The compiler won't tell you if you have methods with the same name that are declared in the class and the category, or in two categories, so you have to be careful to avoid name collision;
This won't appear as a proper class (because Objective C does not have multiple inheritance) so you won't have something in your code called ScrollableZoomableView which inherits from ScrollableView and ZoomableView. That's not possible in Objective C (unlike C++ for example).
You need the -ObjC flag when linking files with categories, otherwise you'll get unrecognized selector errors when you run your code;
You can't get your code called during -init or +initialize, because those belong to the base class. You'll need to initialize your properties explicitly. You can still use +load though;
You can't intercept dealloc either, so you may need to be careful to explicitly deregister your listeners too.
You want something like this:
#interface UIView (Zoomable)
#property (nonatomic) UITapGestureRecognizer * my_tapGestureRecognizer;
#end
#implementation UIView (Zoomable)
-(void)my_enableZooming() {
self.my_tapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(my_onDoubleTap:)];
self.my_tapGestureRecognizer.numberOfTapsRequired = 2;
[self addGestureRecognizer:self.my_tapGestureRecognizer];
}
-(void)my_disableZooming() {
[self removeGestureRecognizer:self.my_tapGestureRecognizer];
self.my_tapGestureRecognizer = nil;
}
-(void)my_onDoubleTap:(UITapGestureRecognizer *)sender {
...
}
-(UITapGestureRecognizer)my_tapGestureRecognizer {
return objc_getAssociatedObject(self, #selector(my_tapGestureRecognizer));
}
-(void)setMy_tapGestureRecognizer:(UITapGestureRecognizer)value {
objc_setAssociatedObject(self, #selector(my_tapGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#end
#interface UIView (Draggable)
#property (nonatomic) UIPanGestureRecognizer * my_panGestureRecognizer;
#end
#implementation UIView (Draggable)
-(void)my_enableDragging() {
self.my_panGestureRecognizer = ...;
}
-(void)my_disableDragging() {
...
}
-(void)my_handlePan:(UIPanGestureRecognizer*)sender {
...
}
-(UIPanGestureRecognizer)my_panGestureRecognizer {
return objc_getAssociatedObject(self, #selector(my_panGestureRecognizer));
}
-(void)setMy_panGestureRecognizer:(UIPanGestureRecognizer)value {
objc_setAssociatedObject(self, #selector(my_panGestureRecognizer), value, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
#end
I'm working with a custom delegate and protocol functionality.
I implemented my class like follows:
#protocol MyDelegate <NSObject>
#required
- (void)update;
#end
#interface MyHandlerClass : NSObject
{
id <MyDelegate>delegate;
}
#property (nonatomic, weak) id <MyDelegate>delegate;
#end
My implementation class looks like:
#implementation MyHandlerClass
#synthesize delegate = _delegate;
- (void)updateRequired: (id)sender
{
if(delegate)
{
[delegate update];
}
}
#end
And from another class I'm setting it like:
[sharedManager setDelegate:self];
But when the updateRequired is triggered it is showing as nil.
Then I added a setter method like:
- (void)setDelegate:(id<MyDelegate>)aDelegate
{
delegate = aDelegate;
}
Everything works fine !!!
Then I changed the updateRequired method (without custom setter) like:
- (void)updateRequired: (id)sender
{
if(_delegate)
{
[_delegate update];
}
}
It is also working fine !!!
I couldn't find why it is not worked for the first case and why it is worked for the other two cases ?
Please help me to find the issue, Thanks in advance
When you use
if(delegate)
You are pointing to the instance variable "delegate".
However, when you use
[sharedManager setDelegate:self]
This is setting the instance variable "_delegate" to "self".
Try this:
if (self.delegate) {
[self.delegate update];
}
You have inadvertently declared one ivar called delegate
id <MyDelegate>delegate;
and another ivar called _delegate
#synthesize delegate = _delegate;
Some suggestions...
don't declare the iVar separately from your #property declaration
don't #synthesize, since XCode 4.4 you don't have to. The compiler will autosynthesize and autocreate an iVar with leading underscore
always refer to you ivar via it's property, inside and outside of your class. Only exceptions are in init, dealloc and inside custom setters and getters.
So this is how your code should look
#protocol MyDelegate <NSObject>
#required
- (void)update;
#end
#interface MyHandlerClass : NSObject
#property (nonatomic, weak) id <MyDelegate>delegate;
#end
#implementation MyHandlerClass
- (void)updateRequired: (id)sender
{
if(self.delegate)
{
[self.delegate update];
}
}
#end
To access your delegate property in the updateRequired method, you can do it by either using the private variable _delegate or by using self.delegate. Because when you synthesize using delegate = _delegate, setters and getters are automatically created.
This line tells the compiler to create a setter and getter for delegate, and that they should use the ivar called _delegate. Without the = _delegate part, the compiler would assume that the property and ivar have the same name.
This a very basic question but I've searched all over and been unable to find an answer that explains well enough for me to get my head around it.
What I want to do is create a method in one class of my iOS app and then call that method from other classes in my app. Could someone explain exactly what I need to do to achieve this? Any help would be greatly appreciated as all my attempts so far have failed!
Thanks.
Objective-C:
You have to import the header of the class that contains the method you want to use (ClassYouWantToUse.h) into the class you want to use it at (TargetClass).
Inside the TargetClass.h or TargetClass.m (depending on the scope you want to give it):
#import "ClassYouWantToUse.h"
Then create an instance of the class you want to use inside the target class either as a property like this:
#property (nonatomic,strong) ClassYouWantToUse *classObject;
Or as an instance variable like this:
ClassYouWantToUse *classObject;
Make sure you initialize it! (usually inside ViewDidLoad):
classObject = [[ClassYouWantToUse alloc] init];
Now you can call any public methods from that class like this:
[classObject theClassMethodWithParam:param1 andSecondParam:param2];
Note: The ClassYouWantToUse class must have the methods that you want to make accessible to others by declaring them in the header file:
- (void)theClassMethodWithParam:(UIImage*)someImage andSecondParam:(NSString*)someText;
Otherwise you won't be able to see these methods.
Swift:
Theres really nothing special about it in swift, just adding this as a reference.
In swift you simply create an instance of the class you want to use:
let classObject = ClassYouWantToUse()
And use it directly:
classObject.theClassMethodWithParam(param1, andSecondParam:param2)
You have two basic options. You can either create or pass-in an instance of the first class to the second class, or you can add a static method to the first class and call it directly using the class object.
For instance, say you have:
#interface ClassA : NSObject {
}
//instance methods
- (int) addNumber:(int)num1 withNumber:(int)num2;
//static/class methods
+ (int) add:(int)num1 with:(int)num2;
#end
#implementation ClassA
- (int) addNumber:(int)num1 withNumber:(int)num2 {
return num1 + num2;
}
+ (int) add:(int)num1 with:(int)num2 {
return num1 + num2;
}
#end
Then you can do:
#import "ClassA.h"
#interface ClassB : NSObject {
ClassA* adder;
}
//constructors
- (id) init; //creates a new instance of ClassA to use
- (id) initWithAdder:(ClassA*)theAdder; //uses the provided instance of ClassA
//instance methods
- (int) add2To:(int)num;
//static/class methods
+ (int) add3To:(int)num;
#end
#implementation ClassB
- (id) init {
if (self = [super init]) {
adder = [[ClassA alloc] init];
}
return self;
}
- (id) initWithAdder:(ClassA*)theAdder {
if (self = [super init]) {
adder = theAdder;
}
return self;
}
- (int) add2To:(int)num {
return [adder addNumber:2 withNumber:num];
}
+ (int) add3To:(int)num {
return [ClassA add:3 with:num];
}
#end
Note that in most cases, you would use instance methods rather than static methods.
You have to use the concept of delegation.
https://developer.apple.com/library/ios/#documentation/General/Conceptual/CocoaEncyclopedia/DelegatesandDataSources/DelegatesandDataSources.html