Why are there two #interfaces for view controllers? - ios

I'm learning some Objective-C, specifically iOS-related stuff. Whenever I generate a new UIViewController, or UITableViewController, etc, both the generated .h and .m files contain an #interface. The application will continue to compile if I delete the #interface from the .m file, also. What is the purpose of this #interface in the .m file?

The #interface in the .m file is a class extension (a category with no name). It's now in the templates to let you put any declaration of internal methods or ivars you don't want to expose to other parts of the code.
With the advent of the modern Objective-C runtime and the progress of clang, a well written class should:
1) have only public methods in the header
2) have ivars and internal methods declared in the internal class extension

Technically, it is a "class extension" (see ("Extensions" section of) the Objective-C intro docs). In practice, it has become common to use this as a "private" interface (it is only "visible" to the file in which it exists). Objective-C does not stop anyone else from calling these methods, but they won't "see" them (think of the .h file as your public interface and this anonymous category as your private interface).
It is handy for declaring #propertys which you don't want to expose publicly.

Related

Without exposing the interface in the public header of framework can I pass a custom object to the client application?

I am working with a objective-C framework.
I have a public framework header "MyPublicHeader.h" exposed to the client application. I have a custom class in the project,
//MyCustomClass.h file
#interface MyCustomClass.h
- (NSString *) methodA;
#end
//MyCustomClass.m file
#inplementation
- (NSString *) methodA {
}
#end
If I want the client to instantiate the class I have to make it as public framework header. I want to hide the interface as a curiosity, is there any way to do it???
First know that nothing can be truely hidden in Objective-C due to the nature of dynamic dispatch and the features in the runtime which allow discovery of methods etc.
That said there are a number of ways to do this, a couple:
Use a subclass. Declare a superclass and publish its interface as part of your framework. Make your class a subclass of this and publish its interface only within the framework. You define one or more init methods in the superclass which return and instance of the subclass, and if you want to expose any further API define it in the superclass with dummy (or faulting) implementations and less the subclass override etc. This approach is similar to the model used for classes like NSString.
A .h file is just text and you can exploit this: make two .h files, say MyCustomClass.h and InternalMyCustomClass.h. In the first just declare the interface with no members, or the API you wish to make public, and publish that to users of the framework. In the second declare the real interface used within the framework. You must make sure to keep all three of the files (2 .h, .m) in sync. This approach would be call little naughty by some, "here be dragons" by others, or "needs must" by yet others...
You might also like to look into "class extensions" which are related to categories.
Hope that satiates your curiosity a little, and keep up with the curiosity its good (except for cats)!
You could create an empty wrapper class which only holds a reference to your MyCustomClass object.
When they create this object you secretly instantiate an object of your MyCustomClass inside and extract it when they pass you an object of the wrapper class.
Not sure if this is exactly what you want to achieve, but could be a workaround.

How can Interface Builder interact with private IBOutlet?

I see that IB job is to unarchive the Nib file, load the objects in the Nib and set those to IBOutlet properties. Some people even use IB as DI framework
But IBOutlet can be private, I mean it can be declared in class extension or implementation section. So how can IB interact with these private IBOutlet?
#interface FPMovieBottomViewController ()
#property (weak, nonatomic) IBOutlet UILabel *usernameLabel;
#end
As described in the Note here: Customizing Existing Classes
By adding the class extension shown above, redeclaring the
uniqueIdentifier property as a readwrite property, a
setUniqueIdentifier: method will exist at runtime on every XYZPerson
object, regardless of whether other source code files were aware of
the class extension or not.
The compiler will complain if code in one of those other source code files attempts to call a private method or set a readonly property, but it’s possible to avoid compiler errors and leverage dynamic runtime features to call those methods in other ways, such as by using one of the performSelector:... methods offered by NSObject.
You should avoid a class hierarchy or design where this
is necessary; instead, the primary class interface should always
define the correct “public” interactions.
If you intend to make “private” methods or properties available to select other classes,
such as related classes within a framework, you can declare the class
extension in a separate header file and import it in the source files
that need it. It’s not uncommon to have two header files for a class,
for example, such as XYZPerson.h and XYZPersonPrivate.h. When you
release the framework, you only release the public XYZPerson.h header
file.
I've highlighted the parts where we can modify existing classes with dynamic runtime. In other languages such as ruby or python this is called monkey-patching.
There's a good article about this: monkeypatching-for-humans. But, in the example given, extension only allows one to add functionality to existing classes, not replace, remove or override. In objc, an accurate example of monkey patching is method-swizzling. Which is not always harmful, because developers have been taking advantage of it to build something like Xcode plugins, or mogenerator.

Difference between declaring instance variable in .h file and .m inside the #interface braces

If some one can brief on declaring instance variable inside .h file inside #interface braces and in .m file #interface braces. like this below
#interface ViewController : UIViewController { NSString *str ; }
#interface ViewController () { NSString *anotherStr ; }
Thx
There's even a third place where you can define instance variables: at the implementation statement:
#implementation ViewController { NSString *yetAnotherString; }
AFAIK, in the olden times you could only define the instance variables in the main interface. The other two places were added later. You can also mix them (as long as they have different names).
The advantage of defining the variables at #implementation and also the class extensions #interface ViewController () level (when done inside an .m file) is that you can hide implementation details from users of your API. In other words, if someone reads the .h file (s)he doesn't know about the variables. This makes the visible API cleaner and is also a concept called "information hiding" which is quite important in object oriented programming: don't expose too much implementation details so you can change the implementation without breaking code using the class.
Note that you can also define IBOutlet variables at all three levels and Interface Builder will detect and use them!
So when you're deciding where to define the variable you can simply ask yourself: Do other people need to see the variable when they see the .h file? IMHO this is only true when you need/want to make a variable #public. For all other cases, you can define them at the class extension or implementation level to make the API cleaner.
Whatever you declare in ViewControllerA.H is public. It means that other view controllers that contain the ViewControllerA object can access use the methods or variables directly. Whatever you declare in .M is private, other view controller can not access it immediately.
As for my own practice, most of the variable (I don't use much) or properties I declare in .M to prevent other view controller to access it directly. It is just like one concept in Object Oriented Programming - Data Encapsulation.
Note: Please be reminded that this should not be confused with #public, #protected, #private like DarkDust mentioned below. It will be another different topic.
In objective-C while you declare the member in .h file, it becomes visible to the other file when .h file is imported as header.
By default all member variables are private. So, user can not use them directly. But with methods of runtime.h and setValueForKey give them an alternate way to set those variable.
To avoid the user to do such mischief, its advisable to declare your private variables in .m file. They are called extensions as well.
For example you have created a variable in your appdelegate file. Now import appdelegate.h file to other .m file. Get the instance of appdelegate by sharedApplication delegate. Now you can set value by below way.
[appdelegate setValue:your_value forKey:#"name of variable"];
Though it was private, user could do so. Its because when you check for auto suggestion window, it will list down your private variable with strike through. To avoid getting those variable inside this window, it is advisable to declare them in .m file.

Class Extension vs Header file [duplicate]

This question already has answers here:
Objective-C class extension
(5 answers)
Closed 9 years ago.
What exactly are class extensions and header files? What are the differences? What is the difference between declaring a property/method in a header file vs in a class extension. I am completely new to objective-c so beginner terminology would be beneficial :)
Thanks in advance!
As the name suggests, they extend the class. A class continuation is another name. The class extension is commonly used to declare private methods and properties. You want the class extension to be visible to the #implementation, and not in the header file (i.e. you want the class extension and #implementation to be in MONClass.m).
Types and methods in the header file are generally intended to be public -- available to any client.
Example: The property declared in the class extension will not be visible/accessible to clients who #import the header, but it will be usable by the #implementation because the #implementation can see the declarations of the class extension.
So this can be used to emulate restricted access for your ivars and methods. This is useful because ObjC methods and properties cannot be specified as private/protected/public (e.g. using #public).
Class extensions differ from categories primarily because extensions may declare storage (e.g. properties which will produce backing ivars).
A header file (.h) is where you would declare properties, methods, and protocols publicly in an existing class. You can then import this file and, of course, use it for your implementation.
An extension is another #interface in your implementation (.m) file. This extends the imported header's internal implementation, adding methods that would not be available should someone or something else import the header file associated with the class.
For more information, check out Apple's documentation on customizing existing classes
Q: What exactly are ... header files
A: Header file - is a file, content of which compiler 'inserts' instead of #import... (#include and other similar directives) line. Header files contains public code: forward declarations of classes, enums, variables, functions and other and other.
Q: What exactly are class extensions …
A: Class Extension - is a language construct, which allows you to extends the interface to the class.
To better understand what it is you must understand what is a class category.
Category - is a language construct, which allows you to add functionality (methods only!) to existing class. Even without subclassing.
Example:
You can add new method to NSImage:
#interface NSImage(YourExtensionName)
- (CGImageRef)CGImage;
#end
A Class Extension (also known as a class continuation, or unnamed category) bears some similarity to a category, but it can only be added to a class for which you have the source code at compile time.
In class extension you can use same things you use in a usual #interface block.
Q: What are difference
A: Header file uses for include to your program some ability (structures, data types, constants, functions and so one). Class extensions uses for extends existing class with some functionality. Usually, class extension is a private interface of a class. The functionality declared by a class extension are implemented in the #implementation block for the original class so you can’t, for example, declare a class extension on a framework class, such as a Cocoa or Cocoa Touch class like NSString.
Q: What is the difference between declaring a property/method in a header file vs in a class extension
A: If you declare property/method in header file, then any user of .h file can access to this property/method. Class extensions uses for declare private interface for you class.
I strongly recommend to you read Apple's Objective-C Programming Guide.

xcode basic explanation needed

I am actually a newby at xcode. I can make out a few things be myself but have questions about what some things do and why they are put there. I have tried to read many e-books, watched tutorials, but they never go into the basics, alway just say "Add this, Click here etc"
Could someone give me some answers to a few questions please.
Ok, I know an ios app is mostly made out of Views, views are controlled by controllers. Each controller has a header (.h) file and a module?class? file (.m). The .h file contains the declarations of variables and functions used in the .m file.
The whole app is controlled by a master "controller" called the "delegate".
Definitions in .h file may be for example an action IBAction or IBLabel or something.
What raises questions for me is for example these lines:
#class FlipsideViewController;
#protocol FlipsideViewControllerDelegate
- (void)flipsideViewControllerDidFinish:(FlipsideViewController *)controller;
#end
#interface FlipsideViewController : UIViewController
#property (nonatomic, assign) id <FlipsideViewControllerDelegate> delegate;
- (IBAction)done:(id)sender;
and why are sometimes in another view controller the delegate class loaded
#class MainViewController;
what does the following do, meaning what is the #interface declaration?
#interface flipAppDelegate : NSObject <UIApplicationDelegate>
what is
nonatomic, retain
sorry for asking really stupid questions, but every tutorial just skips these things.
I can follow a youtube video or a manual, but it doesn't teach me a lot...
Let me try to answer your questions, one at a time.
what is the #interface declaration?
The interface declares a class. By declaring a class, I mean it specifies the instance variables and private/public methods that it contains. Again, the header file only contains the declaration of the methods, and the implementation/body of the methods lies in the module class. So, here-
#interface FlipsideViewController : UIViewController
The class FlipsideViewController derives from/subclasses/extends UIViewController. i.e Is a type of UIViewController but adds its own features.
Similarly
#interface flipAppDelegate : NSObject <UIApplicationDelegate>
Subclasses NSObject and implements the UIApplicationDelegate protocol. A protocol is essentially a set of methods that a class promises to implement (although there can be optional methods).
why are sometimes in another view controller the delegate class loaded
The delegate pattern allows a class to delegate its work to another class that implements the delegate protocol. So, here, FlipsideViewController keeps an instance of the delegate object, so that its flipsideViewControllerDidFinish: can be called.
what is nonatomic, retain
It means that when you set a value to your instance variable, the value's refcount will be incremented and set to your variable. Also, it will not happen as an atomic operation. You need atomic only in a multi-threaded environment.
#synthesize is simply a shortcut to generate getters and setters for your variables.
You really need to read the Objective-C Programming Language from Apple. It's pretty brief, and runs down the basics of the architecture, concepts, and syntax.
To address, briefly, some specifics:
The #class directive is used to declare the name of a class without importing it's header file. It is often used in a .h file declaring a protocol, because a protocol has no implementation, it doesn't need to import the interfaces of other classes (their .h files).
A protocol is a way of declaring what methods and properties a class should have in order to "implement" the protocol.
#interface is used in an interface file (.h) to declare a class, meaning to describe the methods and properties it will have, the protocols it will implement, and the superclasses from which it will inherit. In your example, the class will be called flipAppDelegate, which inherits all of the methods and properties of the NSObject class, and which implements the UIApplicationDelegate protocol.
In your class (.m) file, you will define (with all your code) all of the methods and properties that you declared in your interface file. You include the methods and properties you declared yourself, and from the protocols you implement.
#synthesize is used in a class implementation file (.m) to "synthesize" --- that is, automatically create the code for --- all the properties you declared in your interface (.h) file. Since properties normally just need basic accessors (a "getter" that just returns the current value, and a "setter" that just sets the current value), using #synthesize is a shortcut to let the compiler create the variable to store the value, the getter method, and the setter method for you automatically.
Xcode = An IDE (Integrated Development Environment)
Objective-C = A Language
Cocoa Touch, Media FrameWork, Core FrameWork = Frameworks used in developing for iOS
I'd highly recommend starting by learning Objective-C. At least with a primer first:
https://developer.apple.com/library/ios/#referencelibrary/GettingStarted/Learning_Objective-C_A_Primer/_index.html
There's a wealth of tutorials and videos available from Apple for developers you might want to start on the developer portal.

Resources