I've seen this in some areas of code that I am working with.
searchBar.delegate = (id<UISearchBarDelegate>)self;
My question is...
Why not just make the current class a delegate of UISearchBar by adding <UISearchBarDelegate> in the interface of the class?
Are there times when the above code is better than having the class be a delegate?.
Both ways work for me, but I'd like to learn why I may want to use one over the other.
The cast approach could be considered a cheat. It would be used if the delegate class didn't want to publicly declare the protocol conformance (but then why is it being publicly set as the delegate). Or if the delegate class didn't implement all of the required methods so declaring the protocol conformance would result in warnings.
Generally the better approach is to declare the protocol conformance (either publicly (.h) or privately (.m)).
If you are not using the UISearchBarDelegate in your .h like
#interface ScaryBugData < UISearchBarDelegate>
#property (strong) UISearchBar * searchBar;
#end
then in your .m file then you must do the following to silence the warning
searchBar.delegate = (id<UISearchBarDelegate>)self;
Related
I would like to know which place is best for placing the IBOutlets from storyboards:
a) In the header file (.h)
b) In a class extension created on the .m file
Thank you
Regards
You have to keep in mind that .h is a public header.
So place your IBOutlet's there if they should be accessible by other classes.
However, even though you can do that. I would say that exposing the IBOutlet's in a public header is not a good practice (From object orientation perspective) since you are exposing some implementation details that should be only visible to whom is concerned about.
In short, placing the IBOutlet's in a class extension in the .m is a good practice.
From Apple's Resource Programming Guide: Nib Files:
Outlets are generally considered private to the defining class; unless there is a reason to expose the property publicly, hide the property declarations a class extension.
Class extension is the best place if you don't want to expose that outlet publicly. Your .h should be neat and clean and should only contain those methods or properties which are public (available for other programmers).
In this way you won't confuse your teammate by not having unnecessary ivars and methods deceleration in .h file
It's all about managing the code and making less confusion, otherwise there are no private methods/properties in Objective-C
Also if you check any sample of apple they follow the same pattern. e.g. LoadingStatus.m has code
#import "LoadingStatus.h"
#interface LoadingStatus ()
#property (nonatomic, strong) UIActivityIndicatorView *progress;
#property (nonatomic, strong) UILabel *loadingLabel;
#end
Assuming that this is for a view controller, option b is better as you shouldn't be exposing the outlets publicly for other classes to directly interact with. They should be considered your private knowledge. Your controller should expose a different and more appropriate interface.
If it's a view it's a bit more grey how you should approach the problem as MVC would lead you towards exposing the outlets to allow the controller to use them. MVVM would lead you towards hiding the outlets so that the view is passed a view model object and internally configures the outlets.
The #interface can appear in both the .h file (public properties) and the .m file (private properties). The IBOutlets should be declared in the .m file.
If you are interested read this topic.
Cheers!
How you guys slim down your view controllers?, sometimes you end up implementing a lot of protocols in your view controller, so there’s a lot of code inside the controller itself. Reading about how to slim down view controllers in iOS I found that a common way is to move DataSources (http://www.objc.io/issue-1/lighter-view-controllers.html) to other class, but what about other delegates?, or if you create views by code?. First, I think about move each delegate to a NSObject class, so I try this:
self.locationManager.delegate = [[FRRYPetDescriptionViewControllerLocationDelegate alloc] init];
Then I ask in IRC and somebody suggest categories, so this is what I got so far:
// FRRYPetDescriptionViewController.h
#interface FRRYPetDescriptionViewController : UIViewController
#property (nonatomic) CLLocationManager *locationManager;
#property (nonatomic) TPKeyboardAvoidingScrollView *scrollView;
#property (nonatomic) UIView *contentView;
#end
// FRRYPetDescriptionViewController+Protocols.h
#interface FRRYPetDescriptionViewController (Protocols) <UITextViewDelegate, UIActionSheetDelegate, MFMailComposeViewControllerDelegate, UIGestureRecognizerDelegate, MKMapViewDelegate, UIViewControllerTransitioningDelegate, CLLocationManagerDelegate>
#end
// FRRYPetDescriptionViewController+UIAdditions.h
#interface FRRYPetDescriptionViewController (UIAdditions)
- (void)createScrollView;
- (void)createContentView;
#end
// FRRYPetDescriptionViewController+Callbacks.h
#interface FRRYPetDescriptionViewController (Callbacks)
#end
// FRRYPetDescriptionViewController+LocationAdditions.h
#interface FRRYPetDescriptionViewController (LocationAdditions)
#end
This makes me think, what about “private” methods?, do I need to declare all properties in the view controller header file?. What you guys think about this approach or there’s some common pattern to follow to not end with a fat controller?.
Thank you.
The link that you have referred to has beautiful explanation for less bulky controller's programming. But techniques are bit tricky unless you are a seasoned developer. You have asked about multiple techniques in your question. Please check my views on them below: -
Delegates - I personally prefer to keep the delegate code in my controller itself to avoid unwanted confusion specially when you are working with multiple scenarios within the same controller.
Create Views Programmatically - This is the portion where we can cut the large amount of code from UIViewController. Unless it is a single control such as a single label or button, we should make a custom UIView class and let it set all the common properties for view customisation. Controller should only invoke it with necessary parameters.
Properties in Header File - No, concept of data encapsulation says that we should only make those variables public which are required. Rest should move to private domain so that we external objects can't interfere with the class object functionality. So you should declare these properties in class extension (inside .m file). Moreover it is not required to have all variables as properties, when they are private you can declare them as instance variables as property declaration does nothing but to create the getter/setter for that variable.
Private Methods - Same goes to methods as well. If it doesn't have to be exposed to other objects; it should not be in header file. Keep it in extention as private method.
I know there are a lot of similar questions here but I still need some clarification about this concept.
First of all let me start by saying that I do understand what protocols are and how to use them, what I'm having problem understanding is delegation. I do understand that delegation is when one object in a program acts on behalf of another object, sound very simple but hard to see the whole picture.
1- Is delegation just a way to let the compiler know where to look for the code that will be manipulating the object (UITableView etc.)?
2- Do delegation and protocols work together?
3- Can delegation exist without protocols? If yes, can you show me an example.
4- When we declare a protocol and a class conforms to it, can we say that this class conforming to the protocol is delegating on behave of the protocol?
How much of the above is true?
Thanks a lot
1- Is delegation just a way to let the compiler know where to look for the code that will be manipulating the object (UITableView etc.)?
No, delegation is a design pattern. It's just a concept.
2- Do delegation and protocols work together?
Yes they work well together and it's probably the best practice to use protocol for your delegate.
3- Can delegation exist without protocols? If yes, can you show me an example.
Yes you can. Delegation concept is just to remove intellect of an object and put it in the delegate. For exemple an UITableView does not know how many row it has, or what to do when a cell is clicked, so it asks to its delegate.
But the delegate is still another object.
It's better if it implements a particular protocol, but you can do it without.
For exemple :
I've a MyView that is a subview of a MyCustomViewController.
MyCustomViewController.h
- (void)myViewIsTouched;
MyView.h
#property (nonatomic, weak) MyCustomViewController *delegate
MyView.m
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
[self.delegate myViewIsTouched];
}
There is no protocol in this exemple, but it's still a delegate.
(A better way is still using a protocol instead of declaring the method in the .h)
4- When we declare a protocol and a class conforms to it, can we say that this class conforming to the protocol is delegating on behave of the protocol?
I'm not sure about what're saying. But protocols and delegate are not the same thing. An object implementing a protocol does not mean that it's a delegate.
Delegation allows objects to be able to change their appearance / state based on changes in other parts of your application. Setting a
delegate property on an object will allow the compiler to do some
checks at build-time.
Delegation is often achieved by using protocols, since it allows the
delegate object to be of any class instead of a sub-class of a class
with specific behaviour.
Yes, but this would result in your classes becoming tightly coupled since Foo needs to know about Bar and vice-versa. Using protocols allows you to use any class, hence id property, resulting in a loosely coupled system.
Example:
#class Foo;
#interface Bar : NSObject
- (void)respondToSomeAction:(Foo *)obj;
#end
#implementation Bar
- (void)respondToSomeAction:(Foo *)obj {
NSLog("responding to %#",obj);
}
#end
#interface Foo : NSObject
#property (nonatomic, weak) Bar *delegate
#end
#implementation Foo
- (void)someActionTriggered {
[self.delegate respondToSomeAction:self]
}
#end
When a class conforms to a protocol, the class is compelled to adopt the behaviours of the protocol (implement the methods). It only becomes a delegate if it is given some task to do on behalf of another class, e.g. supply the number of rows in a table.
I'm a huge noob, let's get that straight.
Currently I have in my header file...
#interface ViewController : UIViewController <UIWebViewDelegate>
...but can I have multiple delegates in the h/m files?
Can I add somehow?
The reason I ask this, is because of a warning I'm getting...
"Assigning to 'id' from incompatible type 'ViewController *const __strong'"
The app works fine, but I want to make sure the code is 100% proper.
(LONG STORY SHORT, I'm trying to add location tracking to my app, and I did, and it works fine, but it's giving me a warning because I'm 100% positive I didn't implement it properly, as I am trying to have multiple "XXX.delegate = self;" going on.
I want to somehow have...
self.locationManager.delegate = self;
AND
tapView.delegate = self;
in the same "-(void)viewDidLoad"...
Again, I expect people to literally say "Wtf are you smoking, you are doing this all wrong", because I am.. I need help. Please help. I've been googling all day.
That was a very long winded way of asking how to do this:
UIViewController <UIWebViewDelegate, UITextFieldDelegate, UITableViewDelegate>
There is no issue in doing this at all. You must specify the protocol to remove the warning
You can confirm multiplay delegates i.e.
#interface ViewController : UIViewController <UIWebViewDelegate,SomeOtherDelegate>
Well, you can conform to multiple protocols in your .h file like that:
#interface ViewController : UIViewController <UIWebViewDelegate, UITableViewDelegate, UITableViewDataSource>
Ad you can also conform to more protocols in your .m file with a private class extension like that:
#interface ViewController () <UICollectionViewDataSource, UICollectionViewDelegate>
Don't mix them up
in .h file
#interface YourControllerClass : UIViewController <UIAlertViewDelegate, UIWebViewDelegate UITextFieldDelegate>
You can add Delegates when ever you need them. These Delegates have their methods defined. You can use their methods as you wish
I have used #protocols many times but I think I have been doing it wrong all the time. They have worked always well, but now I want to improve my level so I am trying to do it the better I can.
I always have created a delegate like this:
#protocol CommentViewDelegate;
#interface LZCommentView : UIView
#property (assign, nonatomic) id <CommentViewDelegate> delegate;
#end
#protocol CommentViewDelegate
-(void)showAndHideCommentView;
#end
Now, I have seen that almost all the delegate methods that I see send their own object. Something like this:
-(void)showAndHideCommentView:(LZCommentView *)commentView;
What is the difference between what I did and this? Is one of them better than the other? I have seen that almost everyone who does this, does not use the object in the ViewController.
Another question is, should I use <NSObject> in the #protocol definition?
And the last one, what is better create the #property with assign or strong?
Thank you
Generally, the object that you pass to the delegate can be used so that the same delegate class can be used in different contexts. This gives you more flexibility in cases when a delegate class could potentially be reused.
For example, if showAndHideCommentView needs to interact with a view being shown or hidden, it has two ways of doing it:
Get the view as an argument, or
Reference the view directly, knowing that this delegate is attached to a particular view.
Example of the first approach:
#implementation MyDelegate
-(void)showAndHideCommentView:(LZCommentView *)commentView {
if (isShowing) {
[commentView doSomething];
}
}
#end
Example of the second approach:
#implementation MyDelegate
-(void)showAndHideCommentView {
if (isShowing) {
[self.commentView doSomething];
}
}
#end
The first approach is more flexible than the second one, because it lets you reuse the same code.
According to Apple, it’s best practice to define your protocols to conform to the NSObject protocol, so the answer to your second question is "yes".
As far as the third question goes, the best way to declare delegate properties is with the weak attribute to avoid retain cycles.
1) You should always make your protocol conform to the NSObject protocol. This lets you make use of all of the methods in that protocol.
#protocol CommentViewDelegate <NSObject>
2) Unless you have a good reason to do otherwise, most properties for delegates should be defined as weak. This avoids reference cycles and it ensure the delegate is automatically set to nil if the delegate object is deallocated.
#property (nonatomic, weak) id<CommentViewDelegate> delegate;
3) It's best to include the object in the protocol methods because it offers the most flexibility. It also allows a class to be the delegate of more than one instance. Then the class can tell which instance the protocol method is being called for. Think of a view controller handling multiple buttons or having two or more table views.