Objective-C Basic Class question - objective-c

So I'm a bit rusty getting back into programming and I can't seem to find a good reference for understanding the structure for what I am trying to achieve. So, without further ado I am looking at creating and Class object such as.
#import Assets.h
#interface MainRecord: NSObject {
Assets* assets;
...
}
...
#end
Having a class object within a class, do i need to initialize when the object is created in main? I want to make sure each instance created for MainRecord will always be associated with it's Assets.(in the future these will be written to a file) All of which is mainly for readability and ease of adding objects to this class.

I recommend reading (at least parts of) The Objective-C 2.0 Programming Language, a guide published by Apple. The section called "Defining a Class" will answer the bulk of your questions.
Basically, you don't initialize instance variables in main() — the class defines methods that handle its own variables. (This is common practice for object-oriented programming languages.) In Objective-C you initialize instance variables in an -(id)init method and release them in -(void)dealloc method to avoid leaking memory. For example, see all the -initWith... methods in NSString.

Related

Does Apple recommend using class extensions or variable blocks in implementation?

Apple's doc mentions two ways to create private variables, namely property and ivar, but it does not say which is the preferred way. Which one is Apple's recommended approach or are they equally good in Apple's view?
#interface MyClass ()
#property (nonatomic, strong) NSObject *prop;
#end
or
#implementation MyClass {
NSObject *_prop;
}
Note - I am not asking for personal opinion, but Apple's recommendation. There are similar discussion on this but most have been viewed from personal opinion with no clarification on why one is better than the other and which way Apple advocates (though 99% of Apple sample code uses property)
You should always use #properties because they are safer (e.g. they contain the thread-safe access protection for atomic properties, etc).
And you should also always access properties via their getter/setter instead of directly accessing the instance variables (except in init methods).
As for Apple's recommendations:
Apple engineers answered that at some talks during past WWDC. Sorry no written reference, but I can confirm that they recommend properties over instance variables
In Apple's "Programming With Objective-C" Programming Guide, they mention that you should always prefer using properties over instance variables:
Although it’s best practice for an object to access its own properties using accessor methods or dot syntax, it’s possible to access the instance variable directly from any of the instance methods in a class implementation.
[...]
In general, you should use accessor methods or dot syntax for property access even if you’re accessing an object’s properties from within its own implementation, in which case you should use self
[...]
The exception to this rule is when writing initialization, deallocation or custom accessor methods
Actually in such Programming Guides, like here where they describe the anatomy of an ObjC class, they never mention instance variables and explain how to create them, they only explain properties, so that's a pretty strong indicator that they try to enforce them anyway.

Is it possible to extend(heritance) class in Objective-c as is traditionally conceptualised in other languages?

I am having a lot of repeated code throughout my app classes given that some properties & method are stable across all my views.
I am looking to extend whatever class I am working with so that it automatically inherit all properties and methods that I think should be common to those classes.
I looked into the apple guide on extending classes. But I am left confused in the terms of the level of heritance that I can achieve.
I've successfully created Categories on lets say a UIViewController. But that limits me to only be able to declare Methods. I can not declare Properties on my Category and call them in side my Category or in the Extended Class. I want to be able to declare Properties and use it inside and outside my Extended-Class.
Its my first time trying to extend a class in objective-c taking full advantage of heritance but I do not know if it is possible. Am I missing something?
As an example in the code below every time I try to instantiate activityIndicatorView inside my method _activityIndicator it wouldn't recognise it. I've tried #syntetize and #dynamic but it doesn't work
NOTE: I am seeking an answer based on how to achieve heritance of methods and propeties. not highlighting what categories cant do (as I already tried and know I cant have properties there)
My attempt went as far of
#import <UIKit/UIKit.h>
#interface UIViewController (customViewController1)
#property (strong, nonatomic) UIView *activityIndicatorView;
- (void) _activityIndicator;
#end
#import "UIViewController+customViewController1.h"
#implementation UIViewController (customViewController1)
- (void) _activityIndicator {
//......
}
Your question is too broad, plus it is not clear what your problem is. Yes, you can subclass in Objective-C.
This is all very well documented in Apple's document "Object-Oriented Programming with Objective-C", section "The Object Model", subsection "Inheritance".
Categories are a nice way to add functionality while at the same time conforming to an object oriented principle to prefer composition over inheritance.
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.
When you use the term “extend”, you're talking about creating a subclass. This is, IIRC, how the term is used in Java and some other languages.
Apple uses the term differently (as Hermann Klecker hinted in his first comment). They literally mean extending an existing class with more functionality (in the form of methods)—that's what categories do. This is the normal English definition; extending something in the real world generally does not create a new thing.
Objective-C supports subclasses, too; it just doesn't call them “extending” the superclass. It's called creating a subclass, which inherits from the superclass.
Strctly spoken you cannot add a property to an existing class any differnt than creating a subclass.
If you cannot halp yourself and subclassing is not an option, then you can extend the class with getters and setters for the property that you want to store within the class.
Instead of really storing it as a member/instance variable/property, which you can't do, you could store the object (it cannto be a scalar, must be an object) in the global space using objc_setAssociatedObject(id object, void *key, id value, objc_AssociationPolicy policy).
This is some sort of global dictionary with two keys, the key itself and the ojbect to which you want to associat the stored object to. In your case that is the object of the type of the exended class. The setter stores it there and the getter receives it from there using objc_getAssociatedObject.
You delete an association by sending nil as value to objc_setAssociatedObject
AFAIK retained associated objects (values) are released shortly after the object that holds the associateion (object) is deallocated.
For further details see the Ojbective-C Runtime Reference https://developer.apple.com/library/ios/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
Just: I do not say that this is strictly following the OO paradigm. :-)

Why are Objective-C instance variables declared in an interface?

I'm just getting into Objective-C (Java is my primary OO language).
Defining an object's instance variables in the interface instead of the class seems strange. I'm used to an interface being a public API definition with nothing besides method signatures (not counting constants here).
Is there some reason that state is defined in an interface (even if it is private) and behaviour is defined in a class. It just seems odd that since objects are state+behavior that the definition would be split into two separate places.
Is it a design benefit is some way? A pain in the rear issue that you are just forced to deal with in Objective-C? A non-issue, just different? Any background on why it's done this way?
Or can you put object state in a class and I just haven't hit that part in my book yet?
UPDATE
The answer below was written before the language feature of declaring instance variables in the implementation was implemented. The premise of the question is now no longer valid. As FireLizzard says, nothing needs to go in the #interface that you don't want to be public.
It's a hangover from the fact that Objective-C originated as a fairly thin layer built on top of C. The C way is to define the interface to a module (do not confuse with a Java interface) in a header file and literally include it in each compilation unit. It's akin to automatically copy-pasting the declarations to the top of every compiled file. If that seems primitive, it is because it is, but C is a 40 year old language.
You have to define instance variables - even private ones - in the interface because Objective-C objects are implemented as C structs which are themselves just blocks of memory and named offsets within that block. The struct that represents an object of each class has to include space for the superclass instance variables so subclasses need to know at least the size of the C struct representing the superclass and also the public and protected instance variable offset. That, unfortunately, means that all the instance variables even private ones have to be exposed as part of the external interface.* C++ the other OO version of C suffers from the same problem for the same reasons.
It's a bit of a pain having to write down all the method signatures twice, but you get used to it.
*With the 64 bit runtime, you no longer need to declare the ivars for synthesized accessors in the #interface but since all methods are public, it still means exposing internal state to the outside World, althoug it does alleviate the fragile base class problem.
In Objective C interface does not refer to the instance at all
Brad Cox who designed Objective C decided that the equivalent of C declarations and definitions should be made explicit so each class has a #interface section telling what it looks like externally and an #implementation saying how it is implemented.
Java came along later and changed the object model so that there is only one definition of an object which pulled the #interface and #implementation together. The compiler (and runtime introspection) in effect construct the interface from the code.
The equivalent of an interface in Java is a Protocol in Objective C.
You just get used to it.

How to create a root object in Objective-C without NSObject?

The documentation says:
While not strictly a part of the
language, the isa pointer is required
for an object to work with the
Objective-C runtime system. An object
needs to be “equivalent” to a struct
objc_object (defined in objc/objc.h)
in whatever fields the structure
defines. However, you rarely, if ever,
need to create your own root object,
and objects that inherit from NSObject
or NSProxy automatically have the isa
variable.
While that sounds nice, I wonder how an root object would be created in Objective-C anyways?
This is for learning purposes. I just want to know this. I'd really like to see it.
It's actually a "trap" some people migrating from C# or Java style languages fall into. You simply don't specify a superclass when declaring your class i.e.
#interface MyNewRoot {
Class isa;
}
#end
vs
#interface MyObject : NSObject {
}
#end
In Java or C# these would be equivalent (in the first case the compiler would assume System.Object or java.lang.Object was the superclass), but in Objective-C no such default will be assumed, and hence a new root is created.
However you're now responsible for a number of features for your class that you typically take for granted (even simple things like memory management for allocating or destorying new instances etc). This is what the comment you quoted hints at when it talks about struct objc_object and the isa instance variable etc.

Why subclass NSObject?

What is the purpose/use of NSObject in Objective-C? I see classes that extend NSObject like this:
#interface Fraction : NSObject
In C++ or Java, we don't use any variables like NSObject even though we have preprocessor directives and import statements in both Objective-C and Java.
Why do classes explicitly inherit from NSObject in Objective-C? What are the consequences of not declaring inheritance from NSObject?
We use NSObject to explicitly state what a given class inherits from. I'm not sure about C++, but in Java there's something similar - the Object class. The only difference is that Java doesn't require that classes explicitly descend from Object - the language assumes anything that doesn't have a specified parent class descends from Object. Objective-C is different because it allows you to define different root classes - you are allowed to make a class that doesn't inherit from NSObject.
An example of such a different root class is NSProxy.
Have a look at the GNUstep NSObject source, it shows how the methods interact with the objective-c runtime through C functions.
+ (id) allocWithZone:(NSZone*)z
{
return NSAllocateObject(self, 0, z);
}
- (void) dealloc
{
NSDeallocateObject (self);
}
+ (BOOL) isSubclassOfClass: (Class)aClass
{
return GSObjCIsKindOf(self, aClass);
}
Since object-oriented languages have the concept of an inheritance, in any inheritance hierarchy there is a root class. In Java, the default parent class (if none is provided) is java.lang.Object, whereas in Objective-C, if you don't explicitly declare a parent class, you don't get one. Essentially, your class becomes a root class itself. This is a common mistake among Objective-C newcomers, since you normally want to inherit from NSObject in such cases.
While often problematic and puzzling, this actually allows quite a bit of flexibility, since you can define your own class hierarchies that act completely differently from NSObject. (Java doesn't allow you to do this at all.) On the other hand, unless you know what you're doing, it's easy to get yourself into trouble this way. Fortunately, the compiler will provide warnings if you call a method not defined by a class with no declared parent class, such as those you would normally expect to inherit from NSObject.
As for the "use" of NSObject, check out the documentation of the NSObject class and NSObject protocol. They define common methods used for object allocation, memory management, comparison, hashing, printing descriptions, checking class membership, querying whether objects respond to a selector, etc. Basically, NSObject is "good for" providing the core functionality of Objective-C objects free of charge.
All classes don't necessarily inherit from NSObject but it is the core for many of the classes because it provides things like alloc, retain, and release.
NSObject is the root class of all classes. In my estimation, it's 3 most basic functions are to allocate and initialize memory for you (alloc & init), as well as provide a description function.
Objective-C is all about objects sending messages to other objects -- so NSObject exists to provide that basic functionality.
If this sounds strange to you, you may wish to read more about programming paradigms, particularly object-oriented programming....In a nutshell, however, Objective C is a simple extension to the C language. C gets you the ability to program computer memory, numbers, and characters, but do anything else (like use strings, or show views, for example) you need the extension part, and NSObject is the beginning of that extension.
It may be a useful exercise to pick a class (like NSString, or any for that matter), and follow it's superclasses back to NSObject, to see what functionality each class added.
Hope that helps...
NSObject
The root class of most Objective-C class hierarchies, from which
subclasses inherit a basic interface to the runtime system and the
ability to behave as Objective-C objects.
From Apple documentation - https://developer.apple.com/documentation/objectivec/nsobject.
Basically, most of OOP programming languages explicitly or implicitly specify base class or base functionality. Otherwise you cannot build system where objects communicate with each other. Properties, memory management, message sending mechanism are partly or completely provided or supported by NSObject. Apple provide parts of the Objective-C implementation - https://opensource.apple.com/source/objc4/objc4-723/runtime/NSObject.mm.auto.html, where it's possible to see what is actually inside NSObject.
Also because Objective-C is a language from C-family, so compiler and linker needs to calculate how to layout object in memory and where put and find methods, that's only possible if you know how each of the classes/instances lays in memory and where. In case of Objective-C all base classes (NSObject, NSProxy, etc) have specification of that, so it's possible to calculate their size and add on top all inherited stuff - https://clang.llvm.org/compatibility.html#objective-c.
Consequently compiler don't let to leave a class without base class. So in the end class inheritance should lead to one of the root classes. Here is the error that appears if you don't specify it (from Xcode):
Class 'ClassWithoutBaseClass' defined without specifying a base class