readonly hierarchical model in objective-c - objective-c

In my Objective-C application, I have a hierarchy of subclasses of NSObject which constitute a model. These objects have no functionality on their own, i.e. they only have properties and their sole purpose is to hold data. Furthermore I have a single controller that manages instances of this hierarchy (tree).
Only that controller shall be allowed to make changes to the tree (e.g. the properties of the objects in the tree). Other parts of the program shall have read-only access to the (whole) tree.
What is the easiest way to accomplish this type of access management?

This is a classic case of friend classes. While ObjC doesn't have language support for friend classes, they are not difficult to create.
First, the public interface to your model should declare the properties readonly. That part should be obvious.
Then internally to the model, you make your properties readwrite as needed in a class extension. (This should also be pretty obvious if you're used to ObjC; if it's not obvious, I'll update the answer.)
Now the rest of the story. Create a "Friend" category (or "Writer" or "Protected" or whatever name is meaningful to you).
#interface ModelObject (Friend)
- (void)setSomeProperty:(id)someProperty;
#end
This just tells anyone who imports this category that setSomeProperty: exists. Now your control will import this file (ModelObject+Friend.h) and will be able to set properties. Everyone else imports ModelObject.h and the property looks readonly.
This works for anything you need access to, not just properties of course. I often create immutable classes, and then make a "friend-only" initWithX:andY:andZ: method.

Related

Registering all classes that inherit from a particular abstract class in Kotlin

I have a singleton object called registry.
I also have an abstract base class, say Operation with an abstract field called name. I expect other people to subclass this abstract class and create classes denoting specific operations. I want to be able to store name -> Subclass mapping in my registry object.
Ideally, people who subclass this will not even know about this registration. But if that is unavoidable, I prefer them to write as little code as possible just next to their class declaration.
What is the best way of doing this?
The issue here is name being abstract.
If name were a constructor parameter, then you could simply put the code in the your abstract class's constructor. Every subclass, sub-subclass,… instance will call that constructor (directly or indirectly), so it would always get called. (That doesn't apply to a few special cases such as deserialisation and cloning, so you might have to handle those explicitly.)
However, your abstract class's constructor will get called before the sub(sub…)class constructor(s), and so the instance won't be fully initialised and its name property might not be available yet.
The options I see are:
Refactor your class so that the name is a constructor parameter (and can't be changed thereafter), and add your code to the constructor. (If that restriction is feasible, then this is the simplest solution, both for you and for implementers of subclasses, who won't need to do anything extra.)
Provide a method that subclasses can call once the name has been set up. (You'll have to make it clear in the documentation that subclasses must call that method; unfortunately, I don't know of any way to enforce it.)
It may be possible to use annotations and compiler plug-ins and/or runtime libraries, similar to frameworks such as Spring. But I don't know the details, and that's likely to take much more work; it may also need your implementers to add plug-ins and/or libraries to their project, so probably isn't worth it unless you're doing a lot of other frameworky stuff too.
In each case, you can get the name value and the concrete subclass (using this::class or this::class.java), and store them in your registry. (It doesn't look like you're asking about the internals of the registry; I assume you have that side of things covered.)

Categories & Variables

My question is quite simple.
In Objective C, what is the reason we cant have variables? If we ignore work arounds like Associative reference, extension, dynamic properties etc...what is the goal behind not allowing variables in Categories
If you want to add variables to an existing class, use Subclassing.
If you want to simple add your own methods to existing classes, use Categories.
Categories can be used to declare either instance methods or class
methods but are not usually suitable for declaring additional
properties. It’s valid syntax to include a property declaration in a
category interface, but it’s not possible to declare an additional
instance variable in a category. This means the compiler won’t
synthesize any instance variable, nor will it synthesize any property
accessor methods. You can write your own accessor methods in the
category implementation, but you won’t be able to keep track of a
value for that property unless it’s already stored by the original
class.
The only way to add a tradition property—backed by a new instance
variable—to an existing class is to use a class extension, as
described in “Class Extensions Extend the Internal Implementation.”
What is the goal behind not allowing variables in Categories?
Methods within a Category are added to a class at run-time, this means the compiler won’t synthesize any instance variable, nor will it synthesize any property accessor methods.
On the other hand when using subclassing, the class is compiled at the same time as the class extension.
source
Category provides an ability to add functionality to SDK class. First of all why we need categories we can extend a class to add functionality and data members to it.
Let say you want to extend some functionality of UINavigationController you can subclass and add whatever your requirement. But UINavigationController is also part of some SDK controls e.g. UIImagePickerController and more tab in UITabBarController. What you gonna do to that Navigation Controller you don’t have access to it.
See my blog post for details http://muhammadzahidimran.com/2016/12/09/adding-data-to-sdk-classes-using-categories/

iOS Objective-C accessing ivars from different classes

What is the preferred method of accessing ivars from different classes?
Application Delegate Class
Say I want to access the root controller (#synthesized as rootController) from the Application Delegate class in another UIViewController class. I've read somewhere that you access ivars from the Application Delegate class differently than you access other ivars.
Regular Class
If I want to access some ivars from lets say another UIViewController class. I would like to access the ivar which contains a list (NSArray) of names (#synthesized as names) in class A and get access to them from class B.
The ivars have default access (protected).
Perhaps you can point me to a good tutorial explaining how to access ivars.
The application delegate is a singleton so you can access those properties from anywhere.
In the case of a 'normal' class, and assuming you don't want to make it a singleton, you would normally use the delegate pattern. This means that class A becomes the delegate for class B and class B can call methods that class A will implement, this is how UITableViews work with the DataSource delegate.
This only works if you only need to access these properties from one other class (delegates don't support multi-delegates without a bit of hackery), otherwise I would encapsulate your data in a model which any class can access.
If I understand correctly your question, you will want to get a solid grasp at the Model-View-Controller pattern (which, by the way, is ubiquitous in iOS).
Basically, you should distinguish between your Views and your Controllers -- this is very "natural" in iOS because it is enforced by the framework -- but also between controllers/views and your Model, which is where you have your data, in your case the list of names. Controllers access the model and modify it and also mediate access to it from the Views.
The Model should be factored out someway -- say, in a class of its own -- in order to allow for modularity and low dependencies. In one particular desing (not meaning it is the best or more appropriate for you) the Model could be a Singleton, so that you can easily access it from other objects.
You will understand that a Model to be effective must be properly designed, but this is the way to go.
Check this tutorial and also this S.O. topic.
I think the concept you need here is declared properties: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17
You seems to already using it (with #synthesize).
ivars needs getters and setters to be accessed from the exterior of the class. By using properties, these getters/setters can be automatically implemented with #synthesized.
For the application delegate, i do not understand: do you want to access another controller from the UIViewController via application delegate ?

Share code between classes in Objective-C without inheritance?

Since Objective-C does not support multiple inheritance, is there some other mechanism to share code between classes?
I'm writing a Cocoa library on top of an existing xml schema. Many elements in the schema (for example, ) are used in multiple types. I was hoping to centralize this somehow, so that I didn't have to add #property NSString *name and the associated code to generate the xml for the name property in every single class that has a name attribute. That would be fairly straightforward if multiple inheritance were supported, but I don't know how to do it otherwise.
The best thing I can think of is to create a common superclass that has a superset of methods to encode each optional property, then call the appropriate methods (i.e. encodeName) in the encoding method for each class. Does that seem like the best way to go?
I would recommend you create a new Category with your properties/functions etc and add said category to NSObject. That would make all properties and functions available to all subclasses of NSObject. It's not exactly multiple inheritance but provides a great amount of flexibility.
It is actually possible to add data to a class at run time using the runtime's Associative Reference functions. It's a little deeper than normal SDK work, but works quite well. It's not the same as a full property with getters and setters, but it does associate objects with an instance.
If the methods are only required on certain objects then maybe a sub class from that class is the way to go or a category on that specific class would be better. The category on NSObject is quite a wide net to cast.
If you want to add additional state then sub classing is probably your safest bet.
If you do add a category make sure you prefix your methods with something unique so to avoid any conflicts. E.g. PSMySpecialMethod as opposed to mySpecialMethod

What is the difference between inheritance and Categories in Objective-C

Can some one explain to me the difference between categories and inheritance in Objective C? I've read the entry in Wikipedia and the discussion on categories there doesn't look any different to that of inheritance. I also looked at the discussion on the topic in the book "Open iPhone Development" and I still don't get it.
Sometimes, inheritance just seems like more trouble than it is worth. It is correctly used when you want to add something to an existing class that is a change in the behaviour of that class.
With a Category, you just want the existing object to do a little more. As already given, if you just want to have a string class that handles compression, you don't need to subclass the string class, you just create a category that handles the compression. That way, you don't need to change the type of the string classes that you already use.
The clue is in the restriction that categories only add methods, you can't add variables to a class using categories. If the class needs more properties, then it has to be subclassed.(edit: you can use associative storage, I believe).
Categories are a nice way to add functionality while at the same time conforming to an object oriented principle to prefer composition over inheritance.
Edit January 2012
Things have changed now. With the current LLVM compiler, and the modern, 64-bit runtime, you can add iVars and properties to class extensions (not categories). This lets you keep private iVars out of the public interface. But, if you declare properties for the iVars, they can still be accessed / changed via KVC, because there is still no such thing as a private method in Objective-C.
Categories allow you to add methods to existing classes. So rather than subclass NSData to add your funky new encryption methods, you can add them directly to the NSData class. Every NSData object in your app now has access to those methods.
To see how useful this can be, look at: CocoaDev
One of favorite illustrations of Objective-c categories in action is NSString. NSString is defined in the Foundation framework, which has no notion of views or windows. However, if you use an NSString in a Cocoa application you'll notice it responds to messages like – drawInRect:withAttributes:.
AppKit defines a category for NSString that provides additional drawing methods. The category allows new methods to be added to an existing class, so we're still just dealing with NSStrings. If AppKit instead implemented drawing by subclassing we'd have to deal with 'AppKitStrings' or 'NSSDrawableStrings' or something like that.
Categories let you add application or domain specific methods to existing classes. It can be quite powerful and convenient.
If you as a programmer are given a complete set of source code for a code library or application, you can go nuts and change whatever you need to achieve your programming goal with that code.
Unfortunately, this is not always the case or even desirable. A lot of times you are given a binary library/object kit and a set of headers to make do with.
Then a new functionality is needed for a class so you could do a couple of things:
create a new class whole instead of a stock class -- replicating all its functions and members then rewrite all the code to use the new class.
create a new wrapper class that contains the stock class as a member (compositing) and rewrite the codebase to utilize the new class.
binary patches of the library to change the code (good luck)
force the compiler to see your new class as the old one and hope it does not depend on a certain size or place in memory and specific entry points.
subclass specialization -- create subclasses to add functionality and modify driver code to use the subclass instead -- theoretically there should be few problems and if you need to add data members it is necessary, but the memory footprint will be different. You have the advantage of having both the new code and the old code available in the subclass and choosing which to use, the base class method or the overridden method.
modify the necessary objc class with a category definition containing methods to do what you want and/or override the old methods in the stock classes.
This can also fix errors in the library or customize methods for new hardware devices or whatever. It is not a panacea, but it allows for class method adding without recompiling the class/library that is unchanged. The original class is the same in code, memory size, and entry points, so legacy apps don't break. The compiler simply puts the new method(s) into the runtime as belonging to that class, and overrides methods with the same signature as in the original code.
an example:
You have a class Bing that outputs to a terminal, but not to a serial port, and now that is what you need. (for some reason). You have Bing.h and libBing.so, but not Bing.m in your kit.
The Bing class does all kinds of stuff internally, you don't even know all what, you just have the public api in the header.
You are smart, so you create a (SerialOutput) category for the Bing class.
[Bing_SerialOutput.m]
#interface Bing (SerialOutput) // a category
- (void)ToSerial: (SerialPort*) port ;
#end
#implementation Bing (SerialOutput)
- (void)ToSerial: (SerialPort*) port
{
... /// serial output code ///
}
#end
The compiler obliges to create an object that can be linked in with your app and the runtime now knows that Bing responds to #selector(ToSerial:) and you can use it as if the Bing class was built with that method. You cannot add data members only methods and this was not intended to create giant tumors of code attached to base classes but it does have its advantages over strictly typed languages.
I think some of these answers at least point to the idea that inheritance is a heavier way of adding functionality to an existing class, while categories are more lightweight.
Inheritance is used when you're creating a new class hierarchy (all the bells and whistles) and arguably brings alot of work when chosen as the method of adding functionality to existing classes.
As someone else here put it... If you are using inheritance to add a new method for example to NSString, you have to go and change the type you're using in any other code where you want to use this new method. If, however, you use categories, you can simply call the method on existing NSString types, without subclassing.
The same ends can be achieved with either, but categories seem to give us an option that is simpler and requires less maintenance (probably).
Anyone know if there are situations where categories are absolutely necessary?
A Category is like a mixin: a module in Ruby, or somewhat like an interface in Java. You can think of it as "naked methods". When you add a Category, you're adding methods to the class. The Wikipedia article has good stuff.
The best way to look at this difference is that:
1. inheritance : when want to turn it exactly in your way.
example : AsyncImageView to implement lazy loading. Which is done by inheriting UIView.
2. category : Just want to add a extra flavor to it.
example : We want to replace all spaces from a textfield's text
#interface UITextField(setText)
- (NSString *)replaceEscape;
#end
#implementation UITextField(setText)
- (NSString *)replaceEscape
{
self.text=[self.text stringByTrimmingCharactersInSet:
[NSCharacterSet whitespaceCharacterSet]];
return self.text;
}
#end
--- It will add a new property to textfield for you to escape all white spaces. Just like adding a new dimension to it without completely changing its way.