In an iPhone app, I need to customize the look of a UINavigationController class. For instance, make the bar and font size bigger. My client really needs that, and bigger buttons aswell.
So, instead of writing the class from scratch, I decided to subclass UINavigationController. My question is, can I customize any method or attribute's default value? Is there any restriction while subclassing a class?
It depends what you mean by "restriction". The runtime will not prevent you from subclassing whatever you like, but there are a few gotchas. (Although your answer is specifically about UINavigationController, the title and concept are bigger, so I'll address the bigger issues.)
There may be variables in the parent class which are marked #private and child classes cannot access, versus the default of #protected, which are accessible.
Some classes are designed for subclassing (and most AppKit and UIKit classes are) but for others it is extremely unwise. For example, key foundation classes like NSString, NSMutableArray, etc. are actually class clusters, meaning an instance of the class may actually be one of several private classes.
Classes that are designed for subclassing will usually document the key methods which must be overridden. For example, NSDictionary and NSMutableDictionary describe a few "primitive" methods which every other method calls down to, so overriding 2 or 3 in each case is sufficient to change the behavior without re-implementing everything else.
Be extremely careful to call the parent class' implementation of your overridden method if and when it is necessary. This can be especially important in UI classes, which often have more complex behavior than simple get/set data classes.
In this case, you're exactly right to not write the class from scratch — that would be a Bad Idea™. If you want to change the default value of an attribute (field?), you can set the desired value in an initializer after calling the parent's initializer. However, if you do this, make sure you're not hosing something in the parent class, and always test thoroughly.
Apple has reserved methods that start with "_" for their own use, so I'd echo Marc's caution to not touch those at all. Everything else is fair game, within reason of course. :-)
No, feel free to go nuts. Many Cocoa classes are not as subclassing-friendly as others (especially those that are meant to rely more on delegate control) and may not expose the functionality you need, but you can feel free to subclass any method that's not private (begins with a _ prefix). You could even subclass those if you really wanted to, although on the iPhone chances are Apple would reject your app.
Related
Working on a maintenance project, I am struggling with lot of messy code. In the current assignment, I found that the previous developer has defined property (and synthesize) for each and every iVar and IBOutlet of the class.
As per my understanding, I was used to declare properly of only those variable, which I intended to use outside of that class. And most of the time, I need not to declare property (and synthesize, of course) for any of the IBOutlet.
Can I have any Answer or Document on "When to declaring property and synthesize is needed (or essential)" ?
EDIT: After reading the Post which Dr.Kameleon Pointed, another Question comes to my mind: What loopholes can be there in code, If I declare each and every iVar as a Propery and Synthesize them? Can I go that way?
I think in general it's hard to argue that having an extra property or two is all that bad. That being said, including lots and lots of properties and variables can clutter things up and make the code difficult to understand and maintain. And you don't really need an IBOutlet for every frazmabob in your view. So if you're looking to trim the fat a bit, just get rid of anything you don't need to manipulate at runtime. It sounds simple because it is - the only reason to include a variable/property is if you anticipate using it at runtime.
As for presenting properties to the outside world, you're right, it is a primary concept of OO programming to hide things when they don't need to be presented. This is very important if you are part of a team and you don't want others mucking with your data. So go for it - clean up that code and make life easier for yourself and others down the road.
There is no as such rule about when to use property and when to use ivar. Using both have their own advantage-
Using ivar-
using ivar provide small performance benefit.
User has to do memory management manually by reference counting
Using Property-
this ensures KVO compliance code.
By using property, memory management is taken by Accessors.
You can checkout following topic for more insight information - http://cocoawithlove.com/2010/03/dynamic-ivars-solving-fragile-base.html
In my opinion, i always prefer to use property as it has lot of benefit over ivars.
AFAIK view controller classes should be used for managing their views, IBActions, IBOutlets and other view-screen related stuff only. This means that view controller class should be as lightweight as possible, only concerning about managing its root and inner views. However, sometimes we are tempted to leave the code inside view controller class and not to move to other custom class.
Currently, I always create custom classes for models(database tables or custom objects), parser wrappers, heavy computations and for other logic that is more or less big and might be considered as a separate class. However, very frequently, I'm leaving some relative small computations, simple checking, simple download and other small code stuff inside view controller classes, because I'm lazy (and who is not?) and I'm not comfortable with having a bunch of tiny classes just because, theoretically, some several code statements does not belong to some view controller class. I understand that those tiny classes might evolve to bigger and real classes later, during other versions of an app, but however, might not.
IMHO, if you will be very concerned about the 100% pureness and cleanness you will spend more time (well, at least during initial versions of the app), but you will never know if the product will evolve or if it will be abandoned. There's always some trade-offs the developers are facing with.
It would be interesting to hear, what in-house rules do you use for designing your classes.
Two questions really that when/where you should do something which is whether you've stuck to the pattern or not.
And how
How is much less clear cut, particularly when practicality and pragmatism start getting in your face.
We tend to go for a static class for simple stuff e.g. a DateUtility class for parsing and formating dates in different formats.
And Aggregation for larger stuff, i.e. a downloader.
If you want reuse, decouple is the basic rule, so just because something was big wouldn't necessarily mean a different class.
Personally i like to have a strict class separation also if that means have a huge amount of files :(
Every object has its purpose and if i found some really generic operations i prefer create an "helper" class where encapsulate methods that cannot be specific of a context.
The really difficult step is to be strict on your decision and don't be lazy :) because by your question it's clear that you understand how it's important be rigorous on your code!
Say I want to create my view controller class with 2 superclasses; UIViewController and UIView.
is this possible? or is there another way of getting round this?
Multiple inheritance is not supported by Objective-C (hopefully, because multiple inheritance is generally synonym of bad design and also lead to potential complex problems like the diamond problem).
Use protocols instead if you need the concept of "common programming interface" (common API for multiple classes)
Note anyway that making a ViewController inherit UIView is nonsense anyway as this is not the same objects at all and in separate parts of the MVC pattern. (UIViewController being in the "Controller" part, probably holding behavior stuff, whereas UIView is the "View" part and not the Controller part, and only have to manage the display/visible representation of your stuff).
There is obviously some misunderstanding of the MVC pattern (omnipresent in Cocoa framework) and I suggest you take some time to read more about MVC. This may not be straightforward at the beginning if you are new to OOP but this is worth understanding as it would be easier for you once you understand it fully.
No multiple inheritance in Obj C. However you can achieve your goals using Protocols, composition and message forwarding. And might I add, just searching for the above 3 keywords in Apple's dev documentation pages is an excellent way to learn and get started.
One of the tasks of a view controller is to carry enough state so that the view can be released and rebuilt to handle low memory situations. So it is a likely a bad idea.
In general, the iOS framework uses delegates as a neat way to combine the behavior of 2 superclasses: you subclass one (or both) and have an instance of the other class as member variable. Neat and simple and probably a better design anyway.
The reason I ask is because I have separate domain objects which I map from the NSManagedObject subclasses so as to keep my data access logic separate.
But I think its going to be a problem for updating.
I wouldn't say that NSManagedObject subclasses must be passed to a controller object: In theory you could do what you're describing, and build a "front end" layer that sits between your Core Data model and your controllers – you're creating a lot more work, of course, and it might be just as easy to throw out your old model and start over, if and when you ever do decide to stop using Core Data.
You may also have to put more effort into keeping your model objects separate from your controller objects, what with a middle layer that could easily become a hodgepodge of both. It sounds like you've already gone down this road, though, so the question is probably more about the best use of your time and resources, and whether it's more cost-effective to phase out the middle layer or maintain it.
If you mean should you pass MySubclass vs NSManagedObject; it does not matter. The instance is what it is, your subclass. You can call it anything in between id and MySubclass.
So you can set up your controller to accept just an id or NSManagedObject you can pass it your subclass without an issue. If you want more exposed control to the subclass then you can pass around the subclass.
If that does not answer your question then I suggest you expound upon your question with an example.
I've had some experience developing for the iPhone but am entirely self taught and am trying to improve my practices. This is a question that is probably pretty introductory to programming.
What is the best way (or is it possible) to maintain instance variables with values that are common to all instances of an object? Is it possible to have the creation, modification, and checking of an object and its attributes happen in different places?
Say I have an object that keeps track of the number of times a user swipes the screen. Is it possible to, say, allocate that object in my AppDelegate, and then somehow increment the count variable of that object from different view controllers?
Is it possible to define an instance variable such that it is shared across all instances of the object to which it belongs? That would solve the problem.
So far, I've just made IVARs in my AppDelegate for the things like this that I've needed to keep track of and then just accessed them like this:
((MyAppDelegate *)[UIApplication sharedApplication].delegate).instanceVariable
but I don't know if that's a good practice or not. Probably not.
Maybe this is related to global variables or singletons. Or the prefix "shared" that appears above and I've seen in other places too. I'm just looking for advice or a direction to look. I hope this question makes sense and isn't too general.
I think the question(s) you are asking involve different practices for different situations. To share data among viewcontrollers is one question with a number of solutions, one of the better ones being to use a delegate for all the viewcontrollers.
If you want to have a Class manage all its own objects, even if the objects come and go, you could do one of two things:
Make the Class have a singleton, and keep track of allocations and deallocations in order to know when it should create and then dispose of itself (if needed). This is not a bad way to do it, although it may be more work.
Create a controller class that manages your other class of objects. A good example may be a class of views, controlled by a viewcontroller class.
Let's see what other people suggest.
Matt Gallagher had post a great article on exactly that problem. You can see it at Cocoa with Love.
However, on a multiple view controllers patterns as mahboudz said, delegations is preferred.
In C++ or Java (etc), what you'd be looking for is a "static instance variable", which is exactly what you describe: an instance variable that is shared by all instances of the class. Objective-C does not have such a beast, precisely, but you can use some normal C syntax to give you something very similar.
See the bottom of this page:
http://iosdevelopertips.com/objective-c/java-developers-guide-to-static-variables-in-objective-c.html
(Copy of the code there in case the page vanishes:)
#interface MyClass
{
// ...
}
+ (NSString *)myVar;
+ (void)setMyVar:(NSString *)newVa;
#end
#implementation MyClass
static NSString *myVar;
+ (NSString *)myVar { return myVar; }
+ (void)setMyVar:(NSString *)newVar { myVar = newVar; }
#end
In this case "myVar" is global to the .m file, but because it's marked "static" (this is a C trick), the compiler limits its visibility to only the .m file that it's in. (As with anything like this, keep your eye on multithreaded access if you use that.)
FWIW, if you're building something that generally needs to be robust, a singleton-like object that everybody shares is a good way to go; you get all the normal Obj-C goodness (mem management if you want it) if you do that.
I would look into using a singleton as a resource manager - maybe the resource manager part is not needed for you, but a singleton would greatly help you.
It is definitely bad practice to use keep everything in the app delegate and access it where needed.. at the very least it means code reuse becomes tricky. If you make a new app and want to use a view or control or part of the system, you'd have to also make sure your new app delegate implements all the right selectors and properties.
Also, as your app grows you'll inevitably find your app delegate gets bigger and messier and harder to deal with.
Debugging becomes a pain too as it's harder to work out exactly which pieces of code are involved in a particular problem.
What I do this is to sketch out which parts of the app actually need which pieces of information, and pass those into the ViewControllers as they are created.