Description + sample + explanation: (You can skip to the question section)
I'd like to make an object instance, which can be implemented by different implementations, depend on a condition (the internet status).
Simple declaration
#interface LoginController : NSObject
/** The currently logged-in User. Nil if not logged-in yet. */
#property (strong, nonatomic) User *currentUser;
// Singleton object
+ (instancetype)shareInstance;
/** Abstract methods, will do nothing if call directly. Use inheritance implements (Online/Offline) instead. */
- (User *)loginByEmail:(NSString *)email password:(NSString *)pwd;
#end
#interface LoginControllerOnline : LoginController
// Login will call request to server.
#end
#interface LoginControllerOffline : LoginController
// Login will check data in coredata.
#end
The LoginController's login method actually do nothing (return nil). Instead, the inherited class (Online/Offline) overwrite the parent login's method, with different implementations (as in comments)
And then, I have a manager to define which class should be in use:
#implement InternetManager
+ (LoginController *)loginController
{
return [self hasInternet] ? [LoginControllerOnline shareInstance] : [LoginControllerOffline shareInstance];
}
+ (BOOL)hasInternet
{
// Check with Reachability.
}
#end
This work. But it's not the mechanism I'd like to achieve.
This mean I have 2 instances of inherited LoginController instead of 1.
When internetStatus change from offline to online, I'd like to re-login online (to get session/oauthToken...). But, I'll have to do many things (copy user, change instance, check retained...) before I can actually call from login online
QUESTION:
Is there a way for me to create only one instance of LoginController, which hold the same properties (User), but can has different (dynamic) implementations (Online/Offline)?
Update question:
Quote from Apple's Dynamic typing:
The isa Pointer:
Every object has an isa instance variable that
identifies the object's class. The runtime uses this pointer to
determine the actual class of the object when it needs to.
So, is there a way for me to change this isa pointer of an object instance?
It sounds like the real problem is that you've given these things direct primary ownership of state that you actually don't want them to own — factor it out. There's no copying, just give each an instance of the thing that marshals sate at -init and allow them to talk to it.
Then just do the normal programming thing when you want to do either one thing or another based on a condition: use an if statement.
So, I don't think use of the dynamic runtime is appropriate. However, academically, supposing an interest:
If you really must, use object_setClass, which "[s]ets the class of an object", answering your actual question. Obviously you need the storage to be compatible, so probably your subclasses shouldn't declare any properties or instance variables.
A commonly-discussed alternative for this general area is not changing the class of an existing instance but changing the methods that are a member of the class. So you'd have two alternative implementations of -loginByEmail:password: and set which was the one that actually responded to that selector dynamically. But there's really no advantage over just using an if if you have access to the source code and a bunch of disadvantages around its generally indirect, opaque nature. The whole thing is usually known as swizzling. class_replaceMethod is the key component but just search for swizzling.
Related
I have a framework in obj-c which is included by other modules. I want to allow the modules which are going to include it to provide their own implementation for certain methods.
I can't use subclassing because of some issues around serializing these objects. So, have to rely on using category.
I am thinking of declaring a method/selector for the object and then modules will define the category and implement that method. Something like below:
Framework will declare interface like below:
#interface framework:NSObject
- (void)methodToBeImplemented;
#end
#implementation framework()
- (void)invokeClientDefinedMethod
{
if([self respondsToSelector:#(methodToBeImplemented)]) {
[self methodToBeImplemented];
}
}
//Module-1 will link against this framework and define the category
#implementation framework(methodImplementor)
- (void)methodToBeImplemented
{
...
}
#end
Can I choose not to implement methodToBeImplemented at all in framework and implementation to be provided by the modules themselves.
I know that I can do it performSelector route. But I cringe to do so because I want to send pointers to my method which is not really possible with performSelector
If possible, I would highly recommend using a delegate pattern for your object so that callers can pass a delegate that conforms to a protocol rather than directly extending the class. That's the normal way to implement this kind of system. But if there's a particular reason a delegate is not possible, you can build what you're describing.
What you're looking for is an informal protocol, which is how almost all protocols were handled prior to the introduction of #optional.
What you want to do is define a category on your class in your public header:
#interface Framework (OverridePoints)
- (void)methodToBeImplemented
#end
This declares that such a method may exist, but it does not enforce its actually being implemented. The key is having a name in the parentheses. This can be anything (I used "OverridePoints" here), but it cannot be empty since that would be an extension instead of a category.
Once you have that, then the rest of your ideas work. You can test for respondsToSelector:, and the consumer can implement (or not implement) the category methods just as you describe.
The one danger is that there is nothing preventing multiple parts of the program implementing the same method in categories. That is undefined behavior, but the compiler will not catch it for you.
Let's say I have a simple app that is loading data into a table view. It then allows you to view details (etc).
My table view controller on first load looks something like this below.
Notice I am not using an "property" declarations for these variables. Is this OK? Are there any disadvantages regarding the way memory is then handled?
#interface TblVC ()
{
MBProgressHUD *hudLoad; // new up loading while I go get data
NSMutableArray *results; // set to results after loading data
CLLocationManager *locManager; // get location in view load
}
#end
#implementation TblVC
{
}
- (void)viewDidLoad
{
// spin up the above variables here which can then be used in other methods inside view controller
}
Just use properties. There is absolutely no reason to use the old-style instance variables anymore.
Apple's documentation on properties goes into detail about the benefits. https://developer.apple.com/library/ios/documentation/cocoa/Conceptual/ProgrammingWithObjectiveC/EncapsulatingData/EncapsulatingData.html
An instance variable is unique to a class. By default, only the class and subclasses can access it. Therefore, as a fundamental principal of object-oriented programming, instance variables (ivars) are private—they are encapsulated by the class.
By contrast, a property is a public value that may or may not correspond to an instance variable. If you want to make an ivar public, you'd probably make a corresponding property. But at the same time, instance variables that you wish to keep private do not have corresponding properties, and so they cannot be accessed from outside of the class. You can also have a calculated property that does not correspond to an ivar…
Without a property, ivars can be kept hidden. In fact, unless an ivar is declared in a public header it is difficult to even determine that such an ivar exists.
A simple analogy would be a shrink-wrapped book. A property might be the title, author or hardcover vs. softcover. The "ivars" would be the actual contents of the book. You don't have access to the actual text until you own the book; you don't have access to the ivars unless you own the class.
Quick question about semantics :)
If I was writing a protocol, which is preferred:
// (a)
#protocol MyProtocol
#property (nonatomic, copy) NSSet *things;
#end
vs.
// (b)
#protocol MyProtocol
- (NSSet *)things;
- (void)setThings:(NSSet *)things;
#end
(a) is cleaner code but has the implication that implementing classes will have an ivar for things, which isn't the case in my project. Because of my use case, things cannot be KVO either. It also implies that the implementing class will copy things, which it's not doing in every case for me.
(b) is more accurate code (it's very explicit about what you can / can't do i.e. no KVO) but it's a little messier.
Any opinions?
I am amending my answer that (a) probably is not best for a protocol but best for a non-protocol interface.
I would go with the #property. How a property is implemented is an implementation detail and I never consider that from the outside.
Consider a v1 implementation where the property is only that. In v2 the internals are changed and either the setter or getter is made a method. Totally reasonable, one of the reasons that properties are good, they allow such changes, they hide the implementation details.
Also consider the opposite, in the next version where is is desired to remove the methods and replace them with a property. Again an implementation detail that a property in the first instance covers quite well.
Finally, in this case there is a copy attribute which provided explicit information of how a call with a mutable object will be handled, that is lost in the method implementation.
Protocols define messaging contracts [1]. They are not intended to store data. According to the Apple documentation you are only supposed to add properties to class extensions (you can add properties to categories but the compiler won't synthesize an ivar) [2]. Depending on what you are trying to do I would use one of the two following approaches to be consistent with the documented usage of the Objective-C language:
If you have the source code of the class (its one you created) then use a class extension.
If you do not have the source code sub-class the object.
That being said, if you really need to do it the other way use option (b). It is more corect and more correct is cleaner code!
Here is another question that deals with the same issue.
Good luck
I think case 'a' makes misinformation: class adopting protocol MyProtocol can follow not rules nonatomic and copy.
And for me it's very odd add properties inside protocols. It is going against paradigms of object oriented programming: delegates shold do some action, not provide informations.
So I advice you not use 'a' and 'b' cases, but to think again about yours programm architecture.
Whenever I wanted to inform something to parent class, I have used delegate instead of calling directly parent's functions. I have implemented like this...
eg:
CustomClass *custom = [[CustomClass alloc] init];
// assign delegate
custom.delegate = self; // Here we are giving parent instance like normal method call.
[custom helloDelegate];
In custom class, I have intimated parent like below....
-(void)helloDelegate
{
// send message the message to the delegate
[_delegate sayHello:self];
}
So my doubts , how does it differ from direct call?. Setting delegate variable with self is somewhat equal to giving the parent instance to child and let the child call the function whenever required, how does protocols help here or why do we need protocols? what is the advantage?
thanx
A working example of the advantage of using a delegate as opposed to using a direct relation.
Say you are writing a universal app. You have two view controllers in your code iPadViewController and iPhoneViewController and they both need to get data from a web service. So you create a class for you web service call webServiceDownloaderClass.
Now, both your view controllers need to be notified when the webServiceDownloaderClass has finished.
Your options here...
Option 1 strong coupling
In you iPadViewController you define a method - (void)webServiceDidGetArray:(NSArray *)array;. And in the iPhoneViewController you define the same method.
In order for the webServiceDownloaderClass to call these methods it now needs a reference to each of the controllers...
#property (nonatomic, strong) IPadViewController *iPadController;
#property (nonatomic, strong) IPhoneViewController *iPhoneController;
and then when it finishes it needs to determine which one to call...
if (iPadController) {
[iPadController webServiceDidGetArray];
}
etc....
The cons here are that the view controllers are sort of defining what the web service class does when it is finished. Also, if you add another controller you have another property and no actual guarantee that the controller you referenced actually has the method you are trying to call.
Option 2 delegation
In your we service class you define a protocol.
#protocol WebServiceDownloaderDelegate <NSObject>
- (void)webServiceDidGetArray:(NSArray *)array
#end
and a delegate...
#property (nonatomic, weak) id <WebServiceDownloaderDelegate> delegate;
Now you are defining the actions of the web service class in the web service class. And you only need one reference to any class wants to be the delegate. Also, any class can be the delegate. So now both the iPad and iPhone controller can be the delegate and by conforming the the protocol they are "promising" the web service class that they will implement the required method - (void)webServiceDidGetArray:(NSArray *)array;.
Of course, this is just one case where delegates can be useful.
There are also cases for when you should possibly use a direct relationship rather than delegation.
your question is really about the difference between subclassing rather than implementing protocols (or interfaces in other languages like java)..
with delegates, you are implementing a protocol.. (which is a contract between the class referencing the delegate and the delegate itself).. this gives you more flexibility than subclassing because with subclassing you are automatically inheriting all the methods in the superclass (which is far more restricting than simply using some of the methods of another class.. in other words: subclassing = is a relationship.. whereas as implementing a protocol (same as delegation) = has a relationship.
if you read any book about design patterns.. they will talk extensively about the advantages of loose coupling your code and writing code that prevents modification but allows extension etc etc.. basically using delegation rather than subclassing is one way of fulfilling those design best practices.
A delegate call is not different from an ordinary method call!
What is different is how things are used, and this has nothing to do with the call mechanism. Delegates are used to decouple the definition of the code providing the delegate service from the code "consuming" the delegate service, so that the "consumer" (which, oddly, is usually a service on behalf of the delegate provider) does not have to be coded to know about THAT SPECIFIC delegate provider.
In Objective C delegates are commonly implemented using "protocols", but this is far from the only use of protocols. Objective C uses them extensively in providing common interfaces among the various Cocoa classes.
And, in limited circumstances, one can legitimately implement a delegate using a common superclass rather than a protocol.
If you have two classes that are part of the same development effort and which would not be likely to ever be used apart from each other, there is no need to employ the delegate "pattern" to facilitate communication between them, even though they are is a service-consumer/service-provider relationship. The only reason to do so would be "on spec", in case the "service" were ever reused unchanged in a different project.
So I want to have a "property" on a class but I don't want to just hold that property in memory, I want to actually store it as an NSUserDefault and retrieve it when you get that property.
So as such I have methods like this:
- (void)setUser:(User *)user {
// actually set the user as an NSUserDefault here
}
- (User *)user {
// get the user from the NSUserDefaults and return it
}
As I'm building these methods to do the work for me is there any point in having an #property declaration in the header file?
I'm getting mixed messages. Some people say that you should declare the property to force people to use the getter/setter methods, but I can't see why people wouldn't be forced to use those methods if they're all that are available?
Just looking for a bit of clarification.
Many thanks.
You should use #property because that's the modern way to define properties on Objective-C objects, even if you implement the setter and getter yourself.
Rather than relying on convention you are making your intentions much clearer to the compiler. You will also get better syntax highlighting when using dot-notation in the IDE (although that's arguably an Xcode bug).