#interface ClassB <ClassADelegate> : ClassA
id <ClassBDelegate> delegate;
#end
As the code says, ClassB subclasses from ClassA and handles the formation protocol of Class A. However, the variable "delegate" will be duplicated. (ClassA also has "delegate")
In fact, it can be done without subclassing, but it seems the code is cumbersome, i.e., to use a variable/function of ClassA, I need to write [[ClassB classA] doSomething] instead of [classB doSomething], where doSomething: is a function of ClassA.
Are there any tidy way for me to do that?
In looking at the sample you posted, ClassB conforms the ClassADelegate protocol and ClassB then has a delegate object that conforms to ClassBDelegate. If ClassB conforms to ClassADelegate and is also a ClassA subclass, I'm curious why the ClassADelegate methods are not just part of ClassA to begin with.
So, I would rethink the architecture of this setup and try to keep your model objects and delegates separate, which is the point of the delegate pattern in the first place. If that doesn't make sense for your application, some more concrete information about what your subclassing is meant to accomplish would be helpful.
In doing some work today it occurs to me that Apple does use delegation and subclassing, but definitely not in the way that you've proposed. Have a look at the NSTextField and NSControl classes. NSTextField subclasses NSControl of course and has its own delegate methods but NSControl also has a set of delegate methods. But NSTextField does not conform to the NSControl's delegate protocol (which in fact does is not specified as a protocol anyway).
Related
I understand what purpose protocols serve (to have a type conform to a set list of methods or/and properties), but I don't understand what the purpose is of a protocol with all optional methods. One example would be UITextFieldDelegate.
If all methods are optional in a protocol, why would you conform to the protocol instead of just writing the methods from scratch in your class? I don't see what the benefit or purpose of conforming to the protocol is in this case.
Are the optional methods there just as suggestions of functionality that could be implemented?
Historically, for delegates and data sources in Cocoa, informal protocols were used. Informal protocol was implemented trough a category for NSObject class:
#interface NSObject (NSTableViewDelegate)
- (int)numberOfRowsInTableView:(NSTableView *)tableView;
// ...
#end
Later, optional methods in protocols were introduced. This change leads to better documenting of class responsibilities. If you see in code, that class conforms to NSTableViewDelegate, you suspect that somewhere exists a table view, that managed by instance of this class.
Also, this change leads to stronger checks in compile time. If programmer accidentally assign wrong object to delegate or dataSource properties, compiler will warn.
But your assumption is also correct. Optional methods are also suggestions for possible functionality.
By default, all methods in a protocol are required. Each method has to be marks as optional if the nor required for everything to function correctly.
If all methods are optional in a protocol, why would you conform to the protocol instead of just writing the functions from scratch in your class?
Conforming to a protocol allow your class to tell another object the methods it has without the other object needing to know about your class. This is really useful when using Delegation as it allows the delegate to decide what information they wish to receive/provide to another class.
For example,the UIScrollViewDelegate protocol only defines optional methods. Lets say we have a class Foo that we want to know when things change with a UIScrollView.
If we decided to throw that protocol away and implement the functions from scratch, how would we tell UIScrollView which methods we implement and which methods to call when certain event occur? There is no good way it could find out. When UIScrollView was built, it didn't know about Foo so it can't know what methods it implements. Also, Foo has no way of knowing what methods can be called on it by the UIScrollView.
However, when UIScrollView was built, it did know about UIScrollViewDelegate. So if Foo conforms the the UIScrollViewDelegate protocol, there is now a common definition that both Foo and UIScrollView can follow. So Foo can implement any methods it cares about, like scrollViewDidScroll: and the UIScrollView just needs to check if the delegate implemented the methods in UIScrollViewDelegate.
The protocol establishes a contract for the interface between one object and another. The fact that the methods are optional simply says that you don't have to implement that particular method, but you can if your app calls for it.
Generally, if you're conforming to a protocol for which all of the methods are optional, though, you're doing that for a reason, namely that you plan on implementing one or more of those methods. Just because all of the protocol's methods are optional doesn't mean you will not implement any of them, but rather simply that you can elect which are relevant in your particular situation.
For example, consider the UITextFieldDelegate protocol. You'd generally conform to that because you want to specify, for example, whether certain characters should be allowed to be inserted into the text field or what to do when the return key is pressed. Sometimes you only want to implement the former. Sometimes you only want to implement the latter. Sometimes you do both. But just because you choose to implement one or the other doesn't mean you necessarily want to do other one (but you can if you want). Frankly, though, if you really didn't want to implement any of the methods, you probably wouldn't even bother to specify the delegate of the text field, nor bother to specify that you're conforming to the protocol.
Bottom line, the protocol that consists solely of optional methods basically says "if you need it, this is the documented interface for the methods you may elect to implement". The protocol still is very useful to establish the possible interfaces, but doesn't force you to implement those methods you do not need.
I occasionally instantiate a class from my view controller by passing in the view controller instance itself so that the objects that I create can invoke methods of the controller to update the view.
Is that always, often, or never a bad practice?
Concretely:
ViewController.h has
-(void)updateButtonValue:(NSString*)value;
MyObject.h has
-(id)initWithViewController:(ViewController*)aViewController;
I instantiate that class from my view controller with:
[[MyObject alloc] initWithViewController:self];
thus allowing that MyObject instance to update a button value in my view by a simple call like:
MyObject.m
[self.viewController updateButtonValue:#"example"];
It does not seem ideal since I am passing to MyObject much more (the view controller itself) than it should need, but it is certainly quick and functional. If there is a cleaner approach, such as relying on protocols, that is also succinct, a brief code sample would be much appreciated.
It is always bad practice to pass a class-typed pointer in, as you are tightly coupling your objects together (each object needs to know the class of the other, they might as well be a single object). This is what the delegate pattern is for. It minimises the info MyObject needs (minimally, nothing more than a pointer type id - preferably, a protocol specified by MyObject to offer it some behavioural guarantees)
So to translate your example
MyObject.h
replace...
-(id)initWithViewController:(ViewController*)aViewController;
with...
-(id) init;
(which you can dispense with if you have no further reason to override)
and...
#property (nonatomic, weak) id delegate;
Instantiation in myViewController (which does need to #include MyObject) ...
MyObject* object = [[MyObject alloc] init];
Followed by
object.delegate = self;
(Note that object gets a pointer to myViewController without needing to know anything else about it)
Now you can do this from inside object:
[self.delegate updateButtonValue:#"example"];
However ... you will want to ensure that your delegate can receive the message updateButtonValue:
To do this, you declare a protocol in MyObject.h with the signature of this method
#protocol MyObjectDelegate
- (void) updateButtonValue:(NSString*)string;
#end
And in your viewController, declare that you conform to this protocol using <> in the interface line
#interface ViewController <MyObjectDelegate>
(this is no big deal, ViewController already has to #include MyObject to alloc/init it, so needs no more info to do this)
And expand your property declaration thus:
#property (nonatomic, weak) id <MyObjectDelegate> delegate
Now you have given the compiler enough information for it to ensure that you can only pass conformant messages around. The brilliant thing here is that MyObject can confidently pass messages to MyViewController without needing to know anything about MyViewController other than that it is reached via the delegate pointer.
So far I have seen only CoreData using #dynamic property accessor definitions. What other ways are there for a property to get dynamic accessors in Cocoa object so that they can be marked as #dynamic?
You can generate an accessor at runtime by responding to +resolveInstanceMethod: (which is what Core Data does) or simulate it with -forwardInvocation:. I’ve seen this used in mock model objects which support arbitrary (object-valued) properties, although in that case properties were declared in unimplemented categories so no explicit #dynamic was used. (Actually, I’ve written a stupid hack that makes NSDictionary behave this way.)
I could imagine a similar approach being used for a proxy object.
By default, all declared properties are #dynamic, however you can declare them as #synthesize.
#dynamic means, that you will provide getter and setter implementation in your class, that may be linked to no any i-var.
You can declare a property dynamic yourself. This may be useful if, for example, the getter and setter methods are implemented by your superclass.
I got answer about Foundation magic for this question: What's the most *simple* way to implement a plain data object which conforms key-value-observing?
What's the magic? How it work internally? Because it's dangerous using framework which I can't understand its internal behavior, I want to know its behavior. Currently, I cannot understand how it work without any method definitions.
Apple's documentation describes how KVO is implemented internally.
The gist of it is that when you register an observer on an object, the framework dynamically creates a subclass of the object's original class, and adjusts the object to appear as an instance of this new dynamic class. You can see this if you inspect an object in the debugger after it has had an observer registered.
This new class intercepts messages to the object and inspects them for those matching certain patterns (such as the getters, setters, and collection access).
In a nutshell: Objective-C 2.0's #property declaration creates accessor methods for the named property, so there are method definitions. #property is just a shorthand way to define them which avoids a lot of repetitious boilerplate code.
When you observe a property, a private subclass is created which implements accessors that call the appropriate notification methods before and after changing the property value. A technique known as "isa swizzling" is then used to change the class of the observed object.
As I learn more about KVO and KVC, I have become curious -
How does NSObject provide automatic KVO when accessing setter methods?
If I create a new object with an accessor named setName,
how does an observer get notified when someon calls
[obj setName:#"Mystery"];
Thanks for any feedback
I always explain to people that "nothing is magic in Cocoa; it's just code." But KVO borders on magic. It's called isa-swizzling. Your class is transformed at runtime (the first time anyone observes you) into a dynamically generated sub-class that overloads all getters and setters. Calls to -class are wired to lie to you and return the old class, so you won't see the magic subclasses except in the debugger if you look directly at the isa pointer.
Noticing that KVO must be bizarre is a major step in Cocoa enlightenment. Congratulations.
Key-Value Observing Implementation Details