Is it possible to use a delegate of superclass on subclass
Example: Class A is superclass of class B and superclass A uses the text view method example textviewDidChange. can I somehow call [super textViewDidChange] of superclass A on Subclass B even it isn't on header file of class A
if i rediclare the method on subclass B
When you specify UITextViewDelegate, you're telling the compiler that your class meets the specifications for a UITextViewDelegate. If class A has all the requirements for a UITextViewDelegate, and class B is a subclass, then it too will have all the requirements. Nothing will stop you from assigning any instance as a delegate, so you still have to be careful with that.
Yes,you can. Since class A confirms <UITextViewDelegate> protocol there is no need to redeclare them in header file. Just make sure it implements needed methods.
Related
I made a class which is subclass of UIPopoverBackgroundView:
#interface TestPopView : UIPopoverBackgroundView
#end
Where i tried access the property arrowOffset of UIPopoverBackgroundView class.
but when i implement a method in my subclass ,and i want to access arrowOffset directly (using the form _arrowOffset ,not using getter&setter) , the compiler complains "use of undeclared identifier _arrowOffset
what's the reason ,i can't acess the property directy?
The instance variable _arrowOffset is private iVar to superclass and thus us not directly accessible to subclass. You can use getter/setter to use it in subclass, which works.
I understand how to use delegation with iOS objects that already exist. For example, if I create an instance of a UITableView, and my view controller conforms to the UITableView delegate, I can implement the various methods of the UITableView delegate. My newly create table can receive notifications, for example, when didSelectRowAtIndexPath is called.
My question is why did my table get this particular delegate callback? My understanding is that the delegate is just a list of methods with no implementation. It seems to me there must be a lot more going on. What is really going on "behind the scenes"?
Image if I were to rename all the delegate methods to the following:
- mysteryMethod1
- mysteryMethod2
- mysteryMethod3... Etc
One of these methods is responsible for setting the height of a row at a particular index. Another one these methods will be responsible for editing a particular row.
Everything I read about delegation says the delegator makes a contract with the delegate. The delegate promises to implement the methods. When it does, somehow everything is wired up correctly and everything magically works. What is the magic that I'm not seeing?
I think that in order to know how delegates actually work you should create your own custom delegate first, that way you will see that there is no magic under the hood, you probably can't see the implementation of the actual apple build in delegate methods but I assure you that there is a lot of logic implemented in those but it's just not available for privacy reasons I assume.
When you create your custom delegate let's say for example...
You have Class A and in this class, you start by creating a protocol
protocol ClassADelegate: class {
func changeBackgroundColor(_ color: UIColor?)
}
In this class you have a delegate property like this.
weak var delegate: ClassADelegate?
Let's say that this class is a Viewcontroller and you have an IBACtion on it like a UIbutton, and your goal is that when you tap that button another ViewController in your app change its background color to blue. Inside this action in Class A you do this...
func someAction() {
delegate?.changeBackgroundColor(.blue)
}
,
Let's say that the "magic" happens here in class A, by the way if you are thinking in delegates using UITableview think that UItableView is class A.
ok so now you have Class B that is where you want to change the color right?
Well now class B needs to conform to the protocol like this, just like you also conform to the protocol UITableViewDelegate etc.
class ClassB: UIViewController, ClassADelegate {
}
Now think of the word delegate for a second and think what that means, you are just delegating responsibility to somebody else, right? and yes, in this case, ClassB is going to be the delegated, for that we need to have an instance of Class A in class B just to have access to it's delegate property.
let classa = ClassA()
classa.delegate = self
the final step is just to call the method of the protocol like this..
func changeBackgroundColor(_ color: UIColor?) {
view.backgroundColor = color
}
To conclude if yo see this method in your class but you don't have access to the implementation of the protocol, you will ask yourself "where does this magic color coming from??" but as you saw it just comes from another class where a protocol belongs to, hope this helps.
I just wanted to clear up some confusion that I have with the delegate pattern that should be constructed when there are multiple UIViews and Subviews of these views. To make it clear, let's define some variables.
Let us define these objects as:
ViewController A
UIView B
Subview C
Now, I understand how the delegation pattern works (I think), although I am unsure how to implement this pattern in nested UIViews. Some questions I have are:
Should C contain a delegate implemented by it's super view (B)?
And if yes, should B then pass this information to it's delegate ViewController (A)?
Here's a scenario, let's say C has a UITextView, this text view's height is determined by a string fetched from an API service. B does not have access to the API since this job should be done via the ViewController (A).
Should C then contain a delegate which points to:
The ViewController's (A) delegate implementation?
The UIView's (B) delegate implementation?
Other?
If the answer is ( 2 ) then should B then call the ViewController (A) and pass this information via a chain of events?
Here's a small visual:
A <IBDelegate> <--- B <ICDelegate> <--- C calls Delegate.OnApiComplete(float height);
What is the "Delegate" in this case? (ICDelegate or IBDelegate). And what are the chain of events?
I am just trying to avoid any unnecessary logic to seep into the UIView's when the responsibility should be on the controller.
I understand that you can solve most of these scenario's with a shared object between UIViews, but when it comes to network services, these values need to be retrieved via some sort of callback.
I further clarification is needed, let me know. Any help is greatly appreciated.
So, you have situation like:
ViewController A --> View B --> View C
I would try to ensure that my ViewController A takes decisions both for View B & View C like this:
Create a protocol ViewDelegate and keep both View B and View C
delegate methods in it.
Create a property #property (nonatomic, weak) id <ViewDelegate> delegate; in View B.
Create a property #property (nonatomic, weak) id <ViewDelegate>
delegate; in View C.
From ViewController A while instantiating View B set self as delegate. Like viewBObj.delegate = self.
From View B while instantiating View C set self.delegate as delegate. Like viewBObj.delegate = self.delegate.
This would make ViewController A responding to both View B and View C delegate events.
Delegate are function pointers. Using it, one can call another class' function easily.
To create delegate, common procedure is to, first create protocol and add relevant methods in it (in the class you want to initiate delegate method). This methods can be implemented by class that adopts protocol.
You also need to create generic property of protocol type called delegate property. This will be assigned to instance of class that conforms to protocol.
In your case, class B and class C has some protocols defined in it. Here, B conforms class C's protocol and class A conforms class B's protocol.
Now, class B has object defined of class c in it. In class B, here we need to assign class C's delegate to instance of B(self). (now in class c, delegate property contains instance of B and one can easily call protocol method implemented in class B from class C).
The same scenario happen in class A and B where one can call method (defined in class B's protocol) of class A from class B.
Below is overview of implementation of delegate chain through A -> B -> C.
Class A
Conforms protocol B
It has object of class B
Assign instance of class A(self) to delegate property of class B
In class A, implement protocol methods defined in class B
Class B
Define protocol with methods
Define property of generic type that act as delegate instance
Conforms protocol C
It has object of class C
Assign instance of class B(self) to delegate property of class C
In class B, implement protocol methods defined in class C
Class C
Define protocol with methods
Define property of generic type that act as delegate instance
I hope this will help you understand how delegate works in iOS.
Now in you case, you can conforms protocol of class B and class C into class A (if you don't want any modification into Class B and simply call upper layer's delegate methods).
See below overview
Class A
Conforms protocol B
It has object of class B
Assign instance of class A(self) to delegate property of class B
In class A, implement protocol methods defined in class B
Conforms protocol C
It has object of class C through object of class B
Assign instance of class A(self) to delegate property of class C
In class A, implement protocol methods defined in class C
Class B
Define protocol with methods
Define property of generic type that act as delegate instance
Class C
Define protocol with methods
Define property of generic type that act as delegate instance
If I have a UIViewController subclass (MNIViewController) with a property called match - itself a subclass of NSObject (MNISportMatch).
Now if I make a subclass of the MNIViewController (let's say, MNIFootballViewController) I'd also make a subclass of the MNISportMatch class called MNIFootballSportMatch. In MNIFootballViewController is it safe to redefine the match property as being a MNIFootballSportMatch object instead of a MNISportMatch one?
All the attributes and methods of a superclass are also in the subclass. So if MNIFootballSportMatch is simply a sublcass of MNISportMatch I think it's perfectly safe.
This question already has answers here:
Is it possible to make the -init method private in Objective-C?
(9 answers)
how to block a superclass method to be called to a subclass
(5 answers)
Closed 9 years ago.
Suppose you have a UIView subclass. You define an init method "myInitWithFrame: ... andWhatNot:...". You know you won't be using the init method inherited from UIView ever and your custom init method does some vital custom initialising so that you want to force client classes to never use the inherited initWithFrame method.
Is it possible to hide the standard initWithFrame method that was inherited from UIView?
Actually, you can get compile-time warnings about calling a method on a subclass. Use the __attribute((deprecated)) attribute. If you want people to use -initWithPizza: instead of -initWithFrame:, do this:
#interface MyView : UIView
- (id)initWithPizza:(MyPizza *)pizza;
#end
#interface MyView (Deprecations)
- (id)initWithFrame:(CGRect)frame __attribute((deprecated("Use initWithPizza: instead")));
#end
Putting the -initWithFrame: declaration in a separate category is necessary to avoid Xcode complaining that you declared the method in the header but didn't implement it. Since you're just inheriting it from the superclass, that's fine; you don't have to implement it at all. But if you want to implement it to throw an exception, or call through to -initWithPizza: with a default argument, that's fine.
Of course, this won't stop UIKit from calling -initWithFrame: if it was already going to do so. But if you can guarantee that won't happen, then you're fine.
Actually, you CAN restrict with a subclass. You can override whichever methods you want to block in your subclass's .h file. You can make initWithFrame unavailable by placing the following in your .h file.
- (id) initWithFrame:(CGRect) frame __attribute__((unavailable("message")));
This will make the initWithFrame: method unavailable to anyone using your subclass.
To keep other code form calling this method, you can further restrict by putting this in your .m file.
- (id) initWithFrame:(CGRect) frame
{
return nil;
}
No. You can't prevent the users of your subclass from calling the methods of a superclass. You could override them and throw an exception inside, but that would just produce a broken subclass.
Remember that inheritance works as an "is a" extension, that is, instances of your subclasses should behave normally in any context that doesn't know about this particular subclass but knows about its superclass. It's only in places that have explicit knowledge about your subclass that you can benefit from adding extra initialization and other methods.
For example, UIKit has no knowledge of your subclass. So if you want to make your UIView subclass available from a NIB, you need to use the initialization methods that will be called by the NIB loading system, namely initWithCoder:. You can simply call your own initialization methods inside initWithCoder:. But if there are any additional parameters you would like to pass to the init method, you'll have to provide a way to configure them after initialization.