Domanda

I am trying to teach myself objective-c, but coming from a Python/Java background, it is proving very difficult. I tried to post a bunch of points I am confused on, but it was marked as too vague, so I'll break it into sections.

First, every example of a delegate and outlet I've found uses cocoa view code to get the idea across. Unfortunately, I don't yet understand enough of the code to grasp the example's point. So, can anyone provide a more basic example of a delegate? My understanding is that it is a way of subclassing; how is this better than traditional subclassing? Why does every cocoa project automatically include appDelegate.m? Can delegates be used for other purposes, not just GUI stuff?

Okay, I think I see. So a delegate is a class that conforms to the protocol of some other class. A protocol is simply a list of methods and variables that have to (or can, if set to optional) be implemented in the delegate class. To make a delegate, you have to use the @interface keyword, then the name of your delegate, then (in < > signs) the protocol name? So if class c1 wants to set itself up as a delegate of class c, class c must first specify a protocol, right? You would then be able to implement everything in c's protocol in c1: @interface c1; I feel like I'm missing some bits there, but hopefully I have the concepts right. :) This also explains the mysterious less- and greater-than signs; they declare what interface the delegate implements.

Outlets are similarly always tied to view code. They seem to be some kind of inter-object messaging system. Is that right? Again, an example of a basic outlet that is not mixed in with complex GUI statements would be great. So outlets are never needed? I know that IBOutlet and IBAction are not needed except for use with Interface Builder, but I thought outlets were more general than that? The docs seemed to indicate that they are not even specifically for interfaces, but could be used for anything.

Thanks in advance for any help.

È stato utile?

Soluzione

Update: Delegates don't have to conform to protocols. Protocols just make it easier to require some classes to have methods. It allows you to know for certain an object one has set as a delegate implements a certain method so you can call it safely, and allows the compiler to verify that method is indeed implemented (if you declare a delegate instance variable as id<SomeProtocol> delegate, the compiler will give a warning or error if you try to set delegate to an object of a class that doesn't conform to SomeProtocol.

Protocols help ensure safety, but they're not strictly necessary. A class can have a delegate (or multiple!), and they don't have to conform to any protocols at all.

As for outlets, no, they're specifically and only used with Interface Builder. The IBOutlet and IBAction keywords have no effect on code (they're even stripped out before compile time) - they're only markers for Interface Builder to look for so it knows which properties and methods should be accessible within the interface. The term 'outlet' is a direct reference to something marked as an IBOutlet, and is really not used in any other context that I can tell.

Again, it's okay if you don't understand this right away. Think it over a bit, and at some point, it'll just 'click'. I was caught up on delegates for a long time, just like this, before one day, I realized that delegates really aren't any special. They're regular objects referenced by other objects - it's just that this design pattern has a special name (delegation), and these objects are only called delegates. They could just as easily be called gyros or falafels, and the net effect would be the same. :P
You don't need to name an object delegate for it to be a delegate; it's just a convention.


About delegates: the first thing to understand, and this got me for a while until I had the proper "Aha!" moment, is that there is nothing special about a "delegate". The word "delegate" is just a title for a type of object that another class depends on, very often for content or decision-making. A developer will use a delegate when they don't want to (or can't) tie one of their classes to another class by name - it's an Object-Oriented way of decoupling and making classes more generic.

Now, very often, classes will require delegates to have specific methods they rely on, and one way to ensure that is with a protocol (more commonly known as an interface in Java). Protocols define a list of methods; classes "conform" to a protocol if they declare they do in their interface (e.g. @interface IFObject : NSObject <SomeProtocol> { ... }) and if they implement all the methods they're required to. Protocols can have optional methods as well.

This model is used often with view controllers, views, and the GUI in general because many AppKit and UIKit classes are written to be as generic as possible. NSTableView, for instance, implements the most basic behavior it can possibly implement without requiring any implementation-specific information; for the rest, it relies on other objects, ones that conform to the NSTableViewDelegate and NSTableViewDataSource protocols. Any object can conform to the protocols, as long as they implement the right methods (and in this case, a controller class will usually implement methods from both protocols, but it doesn't have to be so). In fact, one easy way to understand this topic better is to take a look at NSTableView - it's got a delegate property and a dataSource property, but in effect, they're no different. delegate could be called monkeyButt, and the concept would still work. The key is to not treat delegates as a black box - there's nothing special about them.

Delegates can be also used for non-GUI purposes; one concrete example, as you mention, is the app delegate. NSApplication sends a delegate notifications to let it know when the application has been launched (among other things), so it can set up shop. Again, any object can be a delegate to any other object, for any purpose. It's simply a convention.


Briefly about outlets: as others have mentioned, outlets are simply connections between an interface defined in an XIB and your code. They're a way of letting Xcode link up the interface to the appropriate elements so that when your application loads the interface file, it can load up the right pieces of code or execute them.

They're generally an easier way of setting up an interface - they're not strictly necessary (you can create an interface programmatically, without using an XIB file), but if you do decide to go the XIB route, they're how you relate your interface to your code.

Altri suggerimenti

A delegate is an object that is delegated some task by an object it declares itself the delegate of. Let's say an object does some task and then needs to notify the object that "owns" it, so to speak. In order to allow the object to work under any conditions, it cannot be allowed to know what type of object it should contact, so we set its delegate and adhere to its protocol. Setting the object's delegate is like saying "Here's the object I want you to use contact with the messages declared in your protocol. I promise the object actually implements the methods in the protocol." For example, you might see this.

@protocol SpriteDelegateProtocol
    @required
    - (void) projectionMatrix;
    @optional
    - (void) animation:(int)animationIndex willCompleteFrameNumber:(int)frame forSprite:(id)sender;
@end

@interface Sprite
@property (nonatomic, assign) id<SpriteDelegateProtocol> delegate;
@end

The interface for our sprite object declares that it has a property called a delegate, which is of type id. It can be any object, but it must adhere to the protocol in the triangle brackets. If it says it adheres to the protocol, it has to implement the methods declared under the @required and can implement the ones listed under the @optional. It's up to us to determine whether or not our delegate actually implements the optional methods using something like respondsToSelector:. We might even store the return value if we had a lot of methods to do that for.

The application delegate is special in that it is the delegate to our UIApplication object. It receives messages on application state, such as applicationDidEnterBackground:. You can see what methods are in the protocol adhered to by our application delegate here.

Delegates can be used with any object. Any object can say it has a delegate property to set, and that it must have the following methods as shown above. The protocol is essentially a portable interface that can be used to tell another object what we need it to implement so that we can call said methods to delegate some portion of functionality out to it. We can notify our delegate when a task has completed, ask it to give us information (typically called a data source instead of a delegate so that they can be different objects if you want) or ask it whether or not we should do some task at all.

An outlet is a way of connecting a view instantiated in a NIB or storyboard to a property in its controller. So, if you place a UIViewController into your main storyboard and change its class to MyGreatControllerSubclass then proceed to place a button in that controller's view, you might want to hook that button up to an "outlet" (property) in the controller's interface so that you can access the button from the controller later.

No delegates are not a way of subclassing. I also came from Java and have been doing O-C for almost 5 years now.

Delegates generally conform to Protocols, which are the equivalent of Interfaces. What's great about that is it leaves you a lot of flexibility in how you implement the things that are covered by the delegate. So for instance, you will see that Table Views can be implemented by extending UITableViewController or implementing the delegate. That way, if you have a composed view where a user is selecting items from one table and putting them into another, you can do a single controller and have it perform the delegation for both views.

The best way to think about delegates is as examples of message/event oriented callbacks. Have you ever heard the saying that what makes a Framework different from ordinary programming is, with a Framework, it tells you what it wants you to do to ensure the results you seek? That is what delegation is. I was doing a Collection View last night and could not get the edit menu to come up. Just provide delegation of three methods, know nothing about how the menu is invoked, where the Long Press gesture handler is, etc.

Note that Delegates are the glue that makes Dependency Injection unneeded in the O-C world. I prefer them.

Delegates are the common design pattern (http://en.wikipedia.org/wiki/Delegation_pattern), they are not objective-c specific.

Outlets make possibly the binding of Controller and View (GUI). May be you know the MVC paradigm (model-view-controller)? So you build your GUI (the View from MVC) with Interface Builder and bind the elements of this GUI such as Buttons, Text fields and so on to your Obj-C code (the Controller from MVC) using outlets.

Take a look at this post: Conforming Objective-C’s Protocols in C# Codes

Don't worry about the word "C#" in the title, you could just ignore that part. The main part of this post talks about protocols and delegates in Objective-C. This might be helpful.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top