I am reading about iOS programming and I bought the Programming iOS 4 book. There is a introductory part where among several things "Files" is mentioned.
I don't understand how the source files is put together. You have a header file with function declarations, then you have a corresponding file with the function definitions.
Let say you have a Car.h and Car.m & Person.h and Person.m.
Now, if you want to use the Car in the Person class you would import only the Car.h file. How is this sufficient? I don't understand the sequence it put together and builds a program. (Not thinking about the technical stuff, just h/m files.)
The .h or "header file" contains the interface.
The .m or "implementation file" contains the implementation.
Each implementation file is also called a "compilation unit" because the compiler compiles each one separately. Within each compilation unit, the compiler needs to know about types and methods. All it needs to know about a class to create the right code is information about the methods it implements.
So let's imagine you have these files:
Car.h
#import <Foundation/Foundation.h>
#interface Car : NSObject
- (void)drive;
#end
Car.m
#import "Car.h"
#implementation Car
- (void)drive {
NSLog(#"I'm driving!");
}
#end
Person.h
#import <Foundation/Foundation.h>
#class Car;
#interface Person : NSObject
#property (nonatomic, strong) Car *car;
- (void)start;
#end
Person.m
#import "Person.h"
#import "Car.h"
#implementation Person
#synthesize car;
- (void)start {
[car drive];
}
#end
Now when the compiler does its business, it compiles both Car.m and Person.m into Car.o and Person.o respectively. [These then get linked into the final binary, but that's beyond the scope of this question for now].
When it compiles Person.m, the compiler doesn't need to know how - (void)drive of Car is implemented, but it does need to know that it exists, that it is a method that takes no arguments and returns nothing. It doesn't care about the implementation, just that it exists. So you just need to #import the header file of Car to tell the compiler about the methods that exist on Car. The compiler knows that the implementation exists, because you've told it so, and then later on the linker will do it's business to correctly wire up the method call to the correct implementation. How the linker actually does that is a huge topic and I encourage you to go and read about it separately if you don't already understand it.
Note that it's the same for all of the standard NS classes that you use such as NSObject, NSString, etc. You just need to #import Foundation.h from the Foundation framework which tells the compiler about what these classes are and what methods are defined on them.
Creating an executable from a set of source code files is a two stage process.
Firstly, all of the .m files are individually compiled with the Objective-C compiler. This turns each one into a .o file which is an object code file. However, if the code in a .m file refers to things that are defined in other .m files, the compiler does not know about these so it just leaves unresolved references in the .o file.
The second stage is called linking. This takes all the .o files and combines them into an executable. When the linker finds unresolved references in one .o file, it checks all the others to resolve the reference.
Header files allow the compiler to have some information from outside the particular .m file it is currently compiling. So if you have two classes Foo and Bar they are conventionally defined in files Foo.m and Bar.m In order for the compiler to know what class Bar looks like when it is compiling Foo.m we put class Bars interface declaration in a header file (conventionally Bar.h) and import it into your .m file. If you see the line
#import "Bar.h"
it is literally as if the compiler has copy-pasted the entire header file into the source code file before compiling it.
What language have you been using until now? Many languages do it this way including c and c++. The m files are compiled into an actual program, and the h files provide a list of ways to interact with it. While you can still call the methods if you interact with the objective c runtime, the compiler will not guarantee their existence unless they are in the h file.
Now, I say guarantee, but if you dont provide an implementation in the m file, the sibling to the compiler, the linker will have a fit. It will try to make a jump into another m file based on its h file only to tragically discover that it is not there.
The benefits of splitting like this is that you can compile your source into a library and distribute it along with the h files and another application can use it without having the implementation source code.
In summary the m files compile into a lost island of bits and the h files are the map to get around it. If something is on the map that doesnt exist then you will get lost. If something exists but is not on the map then you will have a lot of trouble finding it.
Header files specify what messages ("methods" in other languages) can be passed to a class. That's all the compiler needs to know to compile your code; the linker will eventually wire everything up, so to speak, using the *.m files.
The compiler will handle that for you.
As you stated, a header file contains just the declarations.
Its like a interface to the actual code and that is the only thing Compiler needs to know to fetch the rest.
Related
I know that #class is suppose to speed up compile time, but if I had a case like this:
#import <Foundation/Foundation.h>
#class BNRItem;
#interface BNRItemStore : NSObject
#end
#import "BNRItemStore.h"
#import "BNRItem.h"
#implementation BNRItemStore
#end
Could I do this instead and still get the same compile time:
#import <Foundation/Foundation.h>
#import "BNRItem.h"
#interface BNRItemStore : NSObject
#end
#import "BNRItemStore.h"
#implementation BNRItemStore
#end
(assuming you actually use BNRItem someplace in these files)
it would be the same for BNRItemStore.m, but it is likely to increase compile times and recompilation frequency for anything that #imports BNRItemStore.h -- because it's common that many classes that need to see BNRItemStore do not need to also see BNRItem's #interface.
as that pattern spreads to many headers in your projects, a simple edit to one header can require recompiling a large set of files, with a large set of included files. it also spreads to the indexer, which is continually indexing based on changes.
best to use the forward declarations, unless your project is (and will remain) tiny.
it's actually really nice to be able to declare all your instance variables/properties in the .m -- as this is a fairly new addition to clang. abstraction and build times can improve significantly.
Yes and no.
You wouldn't get the SAME at compile time. #class just tells the compiler its going to see that class, so treat it as a class (take it out, and you get errors) whereas #import tells the compiler to completely import the .h (header) file for that class.
So it will be slower (as you've suggested), especially if the .h (header) file for the class #imports any other files. For an interface you don't need all that functionality, you just need the definition.
But to all intents and purposes the perceived functionality as far as you are concerned is exactly the same, so yes in that respect.
So I noticed that in my new Xcode projects, by default there was a category for my class in my .m file. For example, I'll have this in the .m file:
#interface ViewController ()
#end
#implementation
//Some code
#end
I was wondering is it okay to declare my variables and functions in the category in the .m file, or should I do that in the .h file like before. Basically, what are the best practices in respect to categories.
By the way, my question is sort of related to the below link, but that link does not completely answer my question.
This is not a category, it is a class extension (notice the empty parentheses). You can keep private implementation details, including private ivars, in the extension to limit the declarations in the .h file to the interface of your class. Note that you can add ivars only in the extensions, not in categories.
One very important consequence of this approach is that if you need ivars of types that require additional headers needed only for implementation, you can avoid including that header in the header of your interface, hiding implementation dependencies from users of your class.
I am new in iphone development and i have little bit Question.
My Question is When do we use #class and #import in .h (header )file.And if your answer is #class u can create instance but can not.. use its methods and by use of #import in .h file we can access all method and variable of second class .Then My Question is
if #import contains advantage then why many people used only #class in their .h file.
Please anybody have answer then reply asap.Thanks in Advance.
First of all, you're right with your assumption.
As for advantages:
The #class directive is faster, since it only discloses the Name, and the Inheritance to the Namespace (e.g. the Header File). But #import loads everything, so it's slower and means more load on the system. If your Code is a library for another system, its pretty useful if the headerfiles only load the classname (#class)
For an example. You have the class A, and are importing a Headerfile B from a library. B itself wants to use C. If it imports all data in the B Headerfile, it gets bloated, because you would load it too when importing the headerfile into your class A. But it isn't necessary, that your class A knows what Class C is capable of, because only B is using it.
Have you ever encountered cyclic imports,I suppose you are not.
The other answers are also correct but when it comes to cyclic imports the compiler gives error and you have to use #class instead of import.
quick example
//A.h
#import "B.h"
//B.h
#import "A.h"
In this case compiler will give you the error. So you have to use #class in one of the header files to remove cyclic import. It is true that #class is faster than #import but my projects doesn't have large amount of files that it would take hours to compile it :)
OK, trying to be more clear, then. This is what you usually want:
Use #class in your .h file if the header file doesn't need access to anything in the class you're importing (i.e. it only needs to know that the class exists in order to compile).
Use #import in your .m file to get access to the imported class' properties and methods.
An example, where your class Foo needs to use another class you've created, Bar. Bar also has a custom initializer, -initWithCustomValue:.
MyClass.h
#class Bar
...
Bar _instanceVariable;
MyClass.m
#import "Bar.h"
...
_instanceVariable = [[Bar alloc] initWithCustomValue:1];
This would make sure that you're not exposing unnecessary code (i.e. the contents of Bar) to other classes that might be importing MyClass.h.
From the Apple docs:
The #class directive minimizes the amount of code seen by the compiler
and linker, and is therefore the simplest way to give a forward
declaration of a class name. Being simple, it avoids potential
problems that may come with importing files that import still other
files. For example, if one class declares a statically typed instance
variable of another class, and their two interface files import each
other, neither class may compile correctly.
I'm still coming to terms with classes and objects in Objective-C.
Is a class simply the combination of an interface and implementation file? Or, to put it another way, when would you say to yourself "I need a new .m file for this". At the moment I make a new implementation file when I want to put certain methods and variables in a separate place so that my main code doesn't become massive.
Any help would be greatly appreciated.
Strictly by convention and not by necessity, every new class should have an interface file (.h file) and an implementation file (.m file).
As far as using new .m files for distributing your methods, this is fine.
While convention dictates a pair of .h and .m files per class, the former containing the #interface and the latter containing the #implementation, there is no such requirement and, in fact, many of the system provided classes are divided across several files both in interface and implementation.
Technically, you don't need an #interface at all.
The absolute minimal class definition is:
#implementation Foo
#end
In that the above defines a class Foo that is a new root class. However, the compiler will warn about this.
Effectively, the minimal class definition is:
#interface Foo:NSObject
#end
#implementation Foo
#end
Note that NSObject is intentional; if you are going to make a class that will be compatible with the system frameworks or, even, the system runtime, inheriting from NSObject is pretty much required.
Syntactically, it is up to you as to how you separate the #interface and the #implementation. Traditionally, the interface goes in a header file such that others might #import it and use it while the implementation goes into a compilation unit -- a .m file -- to be compiled and linked exactly once.
But that is convention, not requirement. I've often defined a class --- #interface + #implementation -- entirely in a single .m file solely for use within the #implementation of some other class; effectively, a private class.
Note that class extensions -- #interface Foo() -- were expressly created to allow you to declare additional properties and methods on a class outside of the .h file's #interface Foo:NSObject. It allows a class to effectively have hidden API or to create a property that is publicly readonly and privately read-write.
No it's not. You can place multiple classes in a .h and .m file, althought this isn't deemed good practice.
In Objective-C classes are a pair of interfaces and implementations. These don't have to be in separate files but often are and it is a good way to keep your file structure clean. Often classes represent a little factory and when you have a group of functions that can be grouped together it is a good idea to put them in a class together.
I'll admit to occasionally grouping a few classes together, either with the definitions of all in one .h and the implementations in one .m, or, where some classes are "private", with the definitions AND implementations of "inner" classes in the .m of the major class.
I think it's sometimes good to avoid a proliferation of files this way, and to group interdependent classes together.
You can also go the other way -- spread the definition and and/or implementation of a class among multiple files using "categories" -- but that's a touch ugly and should generally be reserved for extending frameworks classes with specialized functions. (And even at that, done with some apprehension.)
I'm doing a dots game on the iphone for fun ( just simulator) and learning.
this is the game where there are dots and you connect them with "pathways", if you close the square that 4 dots create, you "win" the square.
Now I'm getting some warnings and I'd like to understand how to remove them.
First this is te situation.
I have a class that represents the connection between 2dots, called Pathway.
I have a class called circuit that represent the circuit created by 4 pathways.
so class Circuit has an NSMUtable array of 4 Pathways
and each pathway has an NSMutable array of at most 2 circuits ( each pathway can belong to at the most 2 circuits).
So as you can see there is an import cycle.
I used the #class to include on one of the classes the other because otherwise I'd get errors on compile.
It all works but I'm getting warnings on one of the classes because it can't see the methods for the other.
how can I work around this and what is the proper way to work with these kinds of problems.
File pathway.h
#class Circuit;
#interface Pathway {
}
...
#end;
File pathway.m
#import "circuit.h"
#import "pathway.h"
...
File circuit.h
#class Pathway;
#interface Circuit {
}
...
#end;
File circuit.m
#import "pathway.h"
#import "circuit.h"
...
You don't usually need the full declaration of a dependent class in the header declaring another class. You need the declaration in the implementation files, though. So, split things up.
Import the header file of the respective other class in your .m file. Use the #class directive in your .h file to be able to refer to the classes there.