iOS Objective-C accessing ivars from different classes - objective-c

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 ?

Related

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/

What are the key reasons for using #protocols in Objective C? [duplicate]

This question already has answers here:
What is a Protocol?
(2 answers)
Closed 10 years ago.
Why would I want to use a protocol rather than create a subclass and inherit the methods..?
Please explain it to me, i'm to confused about this topic, i'm not very pleased with the explanation in the book im reading.
Where do I use protocols instead of other ways to get the methods..? if I can subclass a class and get the methods why would i want to use a protocol where i need to define the methods?
Why would I want to use a protocol rather than create a subclass and
inherit the methods..?
Protocols make it possible for unrelated classes to all implement the same interface. Instances of each of those classes can then be used by a client of the protocol. For example, UITableViewDataSource is a protocol that provides an interface by which a table can ask for data from any object that implements the protocol. The table view doesn't care what the type of the object is so long as it implements the data source interface.
Imagine how unpleasant things would be if all table data sources had to inherit from a common class! Objective-C only provides single inheritance, so you'd effectively be constrained to using only a single kind of object for your data source. With protocols, though, a data source can be a view controller, a model object, or perhaps even a remote object.
To be more specific, protocols allow a form of polymorphism. That means that a single object can take several forms: e.g. view controller, table data source, table delegate, scroll view delegate. Because Objective-C is a single-inheritance language, you only get one of those interfaces via inheritance. The rest you implement yourself, but that often makes sense because you generally adopt a given protocol in order to customize some other object's behavior anyway.
Because subclassing and protocols are two different things. Subclassing extends a class with new functionality while inheriting all previous functionality of a specific class while a protocol, when applied to a class, simply adds functionality to it and doesn't inherit anything from it; what that class is usually doesn't matter.
Protocols are most frequently used for the delegate pattern in Objective-C whereby an object can send a message to another object without caring WHAT that object is (i.e. it's class).
Often times, a delegate is declared as:
#property(nonatomic, assign) id < MyObjectDelegate > delegate;
Notice that the class of the property is id -- in essence, you don't care if the object is a car or a turtle -- all you need to know is that it is an object (id) and that it contractually subscribes to the functions you need it to. So if your delegate is type turtle, you can call [delegate myStateChanged]; or, if your delegate is a car, you can call [delegate myStateChanged]. All you need to know is that, if you send a message to it, it will accept it.
I would look up and read about the use of Objective-C delegates as I think it will really help you understand protocols better and how it's different than subclassing. I don't know if you're familiar with other, object-oriented programming languages, but if so, protocols are most similar to Interfaces in other languages.
Protocols are useful because you can implement many protocols, instead you can only extend a single class.

readonly hierarchical model in 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.

When are categories bad/dangerous?

I'm using categories with Core Data. Some of the tutorials I've read and lectures I've listened to say that categories are often considered "bad" practice. But because Objective-C is so dynamic it seems perfectly okay to define methods somewhere else, especially because only public properties of a class can be used. What are the pitfalls I should be looking out for when using categories? Or is there some reason that categories are actually bad practice? The reason I'm using them with Core Data is so that I don't have the rewrite my add-on methods every time I regenerate the subclasses.
The only "danger" I can think of is when you use them to replace methods in the original class rather than subclassing.
When doing this you lose the ability to access the original implementation, which, since it is usually a private method you are overriding, could have unforeseen effects.
Using categories to add extra methods to any object of a particular class is great, and precisely what they are for. Using them for core data, as you are doing, is fine because it does allow you to change your model and regenerate the "vanilla" object without destroying any extra code.
Tip of the hat to #CodaFi for this bit of documentation from apple:
Although the Objective-C language currently allows you to use a category to override methods the class inherits, or even methods declared in the class interface, you are strongly discouraged from doing so. A category is not a substitute for a subclass. There are several significant shortcomings to using a category to override methods:
When a category overrides an inherited method, the method in the category can, as usual, invoke the inherited implementation via a message to super. However, if a category overrides a method that exists in the category's class, there is no way to invoke the original implementation.
A category cannot reliably override methods declared in another category of the same class.
This issue is of particular significance because many of the Cocoa classes are implemented using categories. A framework-defined method you try to override may itself have been implemented in a category, and so which implementation takes precedence is not defined.
The very presence of some category methods may cause behavior changes across all frameworks. For example, if you override the windowWillClose: delegate method in a category on NSObject, all window delegates in your program then respond using the category method; the behavior of all your instances of NSWindow may change. Categories you add on a framework class may cause mysterious changes in behavior and lead to crashes.

How to access a class from another class?

I’m fairly new to OO. If I have two classes A and B that need to exchange data, or call each other’s methods, I need to be able to access an instance of class B from class A. Should I maintain the address of the instance object in a global variable? Should I appoint a (singleton) master class, and make (pointers to) instances of A and B properties of the master class? (AppDelegate comes to mind.)
Is there a straightforward by-the-book way to implement this? Somehow I‘m missing some "best practice" here. I’ve looked through Apple's examples, but didn't find an answer.
EDIT: Since I'm fairly new to MVC design patterns, my question is essentially "Who creates who"?
We're talking about an Audio Player here. 1. When the user selects a song, the UI displays its waveform by creating a viewController which creates the appropriate view. 2. When the user hits play, the UI displays a timeline while the song is playing by overlaying a new view over the waveform. Now, the latter view needs some info from the waveform display viewController. Right now, I'm storing a pointer to the viewController in an instance variable of my appDelegate. This works, but feels extremely strange.
Should I outsource the info that is needed by both classes to some third entity that every class can access easily?
Classes aren't simply departments of code. They are templates for the creation of objects, which you should think of as actors in your program, doing things within their areas of responsibility (which you define—you decide what each object does) and interacting with each other.
While you can handle a class as you would an object, classes generally do not talk to each other. Most of the time, you will create and use instances of the classes—which is what we normally mean by “objects”—and have those talking to each other. One object sends another a message, telling the receiver to do something or changing one of the receiver's properties. These messages are the interactions between your program's objects.
Those weird expressions in the square brackets are message expressions. Nearly everything you'll do with a class or object will involve one or more messages. You can send messages to classes the same as to objects, and classes can send messages just as objects can.
In Cocoa and Cocoa Touch, you typically have model objects, view objects, controller objects, data objects (such as NSString, NS/UIImage, and NSURL), and helper objects (such as NSFileManager). The classes you'll write for your application will mainly be model, view, and controller objects (MVC). The model represents (models) what the user will see themselves manipulating; the view displays the model to the user; the controller implements logic and makes sure the model gets saved to and loaded from persistent storage.
For more information, see Object-Oriented Programming in Objective-C and the Cocoa Fundamentals Guide.
Since I'm fairly new to MVC design patterns, my question is essentially "Who creates who"?
Controllers create and load the model, and load the views, and pass the model to the view for display. Certain controllers may also create other controllers.
It's good to keep a straightforward tree-like graph of ownership from a single root of your program—typically the application object—down through controllers to leaf objects in the models and views. If two objects own each other, that's a problem. If an object is not owned by anything outside of its own class (a singleton), that's usually a problem as well—a sign you need to think some more about where that code belongs. (Helper objects are the main exception; most of those are singletons. Again, see NSFileManager for an example. But they are few and far between.)
Further situation analysis require more information. At first place you should more specify the relation between classes and what exactly do you mean by exchanging data.
Singletons should be generally avoided. If you want to exchange information it is usually sufficient to provide for example instance of the class A to the instance of the class B by some method or constructor. The instance of B is then capable of calling public methods (and accessing public properties) of the instance of A.
A little bit of "best practices" can be learn by searching up "Design Patterns".
You should decide if one class can be an object of another class (encapsulation), or if one class can inherit from the other class (inheritance). If neither of these is an option, then maybe you could make one class (or some of its members) static?
Thanks for your contributions. Additionally, I found information on this page very useful. It lays out MCV considerations for cocoa in a hands-on way and practical language.