I understand that methods available for other classes to call should be in the header file..but I'm a little confused when the #property should be in the header file and when it should be in the implementation file.
How do you make that decision, and what difference does it make?
Any property that you want publicly exposed to the other classes goes in the .h file. The 'private' properties (pun intended) go in the implementation file in a anonymous category or class extension. You might also make the .h version of the property readonly for example, and the .m version readwrite.
An implementation file with properties defined in a Private Category
#interface CPClassFileName ()
#property (nonatomic, retain) NSString *string;
#end
#implementation
...
#end
You put the #property on the header if you want other classes (or developers) to know that there are accessors to your ivars.
To rephrase :
If you want "public" getter / setter you put the #property on the header. If you want them private you put the #property on the .m file.
Related
There are at least 3 methods of creating an IBOutlet in Objective-C, for making iOS 10 App, in Xcode 8.
Method 1: in ViewController.h
#interface ViewController : UIViewController
#property (nonatomic, strong) UILabel *textLabel;
#end
Method 2: in the interface of ViewController.m
#interface ViewController () {
IBOutlet UILabel *textLabel;
}
#end
Method 3: in the interface of ViewController.m, using #property
#interface ViewController ()
#property (nonatomic, strong) UILabel *textLabel;
#end
Given that the textLabel has to be accessed & its text is needed to be updated frequently, which method is the correct way to do so?
That all depends on whether you need your outlet to be accessible to classes outside of the containing one; generally I would discourage this because it is good practice to keep your view controllers responsible for updating your UI and not pass this task around to other classes. With this being said, Method 3 would be the best option, however, if you do have to access your object from another class, then simply use Method 1 so it is exposed in your class header.
Method 2 utilises iVars rather than object properties and is not the proper way to declare outlets, it may even cause unexpected behaviour so it is best to avoid this method.
Your code contains no proper IBOutlet. Outlets are connections to Storyboard.
Method 1
This is a property. As it is in .h file, it can be reached from outside. The Objective-C pattern for public.
Method 2
This is an iVar. Do not use iVars if you do not have to.
Method 3
This is a property. As it is in .m file, it can not be reached from outside. The Objective-C pattern for private.
Method 4
A proper IBOutlet looks like this:
#interface ViewController ()
#property (nonatomic, weak) IBOutlet UILabel *label;
#end
It is a simple property. You have to decide if you put it in .h or .m file depending on whether or not you want to publish it.
The IBOutlet simply makes the property connect-able to Storyboard. It's an annotation for Xcode and does not alter the semantic of your code.
Edit 1:
As Sulthan correctly mentions in the comments:
In most situations the correct design pattern is to hide outlets because it's an implementation detail. External classes should not set data directly using views.
Edit 2:
Why "not to use iVars if you do not have to" (2)
Opinion based:
I consider it as good OOP practice to use getters & setters (and thus not to access the variables directly). Also code is easier to read as you know while reading what x = self.variable (property) and x = variable (local variable) are.
If you have to use iVars for some reason, it is common to (and I would recommend to) prefix the name with _. x = _variable (iVar).
Is it iOS convention to not indent properties, functions, etc defined with a block?
For example defining properties within an interface in a .h file looks like this:
#interface XYZAddToDoItemViewController : UIViewController
#property XYZToDoItem *toDoItem;
#end
In the other languages I'm used to (ruby, php, python, js) it would look like this:
#interface XYZAddToDoItemViewController : UIViewController
#property XYZToDoItem *toDoItem;
#end
Is this the convention? #property is within the #interface block correct?
For the Objective-C interfaces, the definition block is between #interface and #end. All the properties go there.
The convention is indeed not to indent items in the interface definition.
In particular, it's interesting to have a look at Google's Objective-C guide.
No specific reason its like that, as far as I know. I don't indent. However, you could also do this if you wanted to, and remove the #property.
#interface XYZAddToDoItemViewController : UIViewController {
XYZToDoItem *toDoItem;
}
#end
What is the right method of declaration if I want to use single object in my viewcontroller?
to use a #property i my .m file
#property (nonatomic, strong) UITextView *resolutionText;
#property (nonatomic, strong) AWLResolutionView *myView;
or to declare them in my .h file
#interface
{
#private
UITextView *_resolutionText;
AWLResolutionView *myView;
}
For the sake of clean coding I would prefer creating properties in the anonymous category inside the .m file.
However, using #property creates automatically an instance variable for you that has the same name as your property preceded by an underscore (_), that can be accessed from within the .m file. This is called synthesising.
Y
ou can also manually synthesize a property to a custom instance variable using #synthesize.
Apple provided some clear instructions how to write clean code in their developer library.
The best way to declare the private variable should be declared as #property in the extension of .m file . If you see in your .m file there is an extension class called as #interface by default, so declared the same in the extension class. Also no need of writing extra code in.h file for declaring the private variable.
So your first approach is best.
I know that if I use
#interface TPN : UIViewController{
IBOutlet UIView *testView;
}
#property (strong, nonatomic) IBOutlet UIView *testView;
I know that the first one is essentially a private variable that is only accessed within the class. and the second one "#property" is able to be accessed from an instantiated object. I find it odd in most tutorials that people tend to set properties when they are usually changing an outlet from within the class itself. Is there any guideline I should be following?
You no longer need to specify the ivar at all. Nor is there a need to use #synthesize.
Use a property, but make sure it is weak, not strong
#interface TPN : UIViewController
#property (weak, nonatomic) IBOutlet UIView *testView;
In the implementation you can now access the ivar as _testView.
For a private property (above is public) instead put the #property within a category in the implementation file:
#import "TPN.h"
#interface TPN ()
#property (weak, nonatomic) IBOutlet UIView *testView;
#end
#implementation TPN
....
You are right. If you are only going to use the instance variable inside the class, there is no point to make it a property. A property simply means a pair of getter/setter. If you don't need to do anything specially when getting/setting, you can just use the instance variable directly.
Prior to ARC, there was a side benefit to using properties everywhere, in that it was easier to do memory management for object pointers -- properties declared as retain would automatically release and retain for you when you set it, without you typing that code yourself like you would have to do with an instance variable directly. However, now in ARC, the compiler does that for you anyway when you assign, if it's a strong instance variable. So this benefit is now irrelevant.
I would suspect that a lot of the reason people use properties for outlets is because of perpetuation of that usage in almost all tutorials and examples (possibly due to the previous benefit with retain memory management), and they simply don't realize they can do something different.
I was just wondering if it's considered bad practice to have a large number of header files imported into an AppDelegate?
My game has a lot of views (in separate .xib files) that the AppDelegate switches between. At the moment, I am importing 16 header files in my AppDelegate.h file, but is there a better way to manage all of this? Most sample code I've seen has a maximum of around 4 or 5 header files.
Thanks!
It's usually better practice to forward declare your classes in the header file, and then import their headers in your implementation file, for example:
// .h
#import <UIKit/UIKit.h>
#class MyView;
#class MyOtherView;
#class MyOtherOtherView;
#interface MyAppDelegate : NSObject <UIApplicationDelegate>
#property (strong, nonatomic) MyView *myView;
#property (strong, nonatomic) MyOtherView *myOtherView;
#property (strong, nonatomic) MyOtherOtherView *myOtherOtherView;
#end
// .m
#import "MyAppDelegate.h"
#import "MyView.h"
#import "MyOtherView.h"
#import "MyOtherOtherView.h"
#implementation MyAppDelegate
#synthesize myView;
#synthesize myOtherView;
#synthesize myOtherOtherView;
// methods
#end
Doing this will help to avoid situations where you will end up with circular #import references.
I will also often create a header file simply for importing other header files for clarity, e.g. #import "MyViews.h"
Sample code is just that -- sample code, usually meant to clearly demonstrate a single concept. Don't expect your application to look like sample code if it does more than one single relatively simple thing. Expect it to look more like several dozen sample projects all put together (although I wouldn't advise doing exactly that!).