Why Do We Need to Set Delegate to Self? Why Isn't It Defaulted by the Compiler

Why do we need to set delegate to self? Why isn't it defaulted by the compiler?

When mentioning that tableView.delegate = self or tableView.dataSource = self in the desired ViewController, that's means the ViewController is saying "I am responsible for implementing those delegation/dataSource methods", means that this ViewController (self) is taking care of providing the needed method to let tableView knows how it should looks/behaves.

Referring to your questions:

would it ever be possible that we wouldn't want to set
tableView.delegate to self?

Actually it's possible, but this causes to let the tableView appears as an empty tableView (no rows in it), because no one is telling it about how it should looks/behave.

If there is a chance that tableView.delegate is set to something other
than self...well what is that? Can you please provide some examples?

Yes you can, tableView.dataSource/delegate not necessary to be assigned to the same Viewcontroller that contains this tableView (but I find it more readable and understandable).

For example:

In the following code snippets, I assigning the dataSource of the tableView to another separated class (which is not even a UIViewController) on a different .swift file and it completely works fine:

import UIKit

// ViewController File
class ViewController: UIViewController {
var handler: Handler!

@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()

handler = Handler()
tableView.dataSource = handler
}
}

Handler Class:

import UIKit

class Handler:NSObject, UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell")

cell?.textLabel?.text = "row #\(indexPath.row + 1)"

return cell!
}
}

The output works fine as it should.

why can NSObject class be delegate to UIImagePickerController for instance?

The only requirement for a class to be a delegate for a particular class is to implement the protocol required. It doesn't depend upon its inheritance chain. It could be uiviewcontroller, uitableviewcontroller or simply the NSObject.

If your class confirms to the required protocol then its a fair candidate to be the delegate.

iOS : dealloc is not getting called if strong delegate set to self

If you give strong property to your delegate, it will increase retain count. When you pop from navigation queue, it also just decrease retain count. So even-though you pop your view controller, it have retain count via delegate(if strong). Your dealloc only gets call when retain count is 0

Notes: When you set nil to delegate in Disappear, your assigned delegate decrease retain count via setter method and assign nil to delegate. That's why, it get call when set nil.

So you can declare you delegate as weak as like

@property (nonatomic, weak) id<Protocol> delegate;

Delegation question

This would lead to infinite loop (until the stack overflow):

-(void) setDelegate:(id<A_Delegate>)_delegate
{
self.delegate = _delegate; // error, compiler stops right there and doesn't assigns the value from '_delegate'
}

cause self.delegate = _delegate; is calling setDelegate:. You have to assign to the ivar itself.

And I think this is not compiler. It is everything in runtime...

In Swift, does an object conforming to a protocol absolutely need a delegate variable in order to work with the protocol?

If the object already conforms to the protocol by implementing the variables and/or methods, then what is the reason for creating a variable called delegate and setting the type to that of the protocol?

The whole purpose of the protocol in the protocol-delegate pattern is that the only thing this class, which is going to be sending delegate messages to the delegate, needs to know or care about, is that the delegate is an adopter of that protocol — i.e., that it implements the variables / methods. This class doesn't need to know the actual class of the delegate; it just needs to know that that the delegate can be sent the delegate messages.

Thus, it's all about the compiler. The object acting as delegate may conform to the protocol, but the compiler doesn't know that unless this variable is typed as a protocol-adopter. And if the compiler doesn't know, it won't let us send delegate messages to the delegate object! So that's how we type it. That's the minimum the compiler needs to know in order to allow us to send the delegate messages.

Fail in assigning self.delegate it produce unrecognized selector sent

My guess is that you have some other variable named myView here, that's intercepting your call to the MyViewController instance you've just created. Try changing the name of that instance, and see what happens.

Other stuff: ooks like you have a typo in your implementation of MyViewController. Change this line:

@implementation FanglesMapSettingsViewController

to this:

@implementation MyViewController

And you should be good to go. (You're getting that error because the header file doesn't correspond to any implementation, due to the typo, so you never get the benefit of your @synthesize delegate; call.

Also, make sure you declare the proper protocol in TopViewController:

@interface TopViewController : UIViewController <UIScrollViewDelegate, MyViewControllerlDelegate> 

And change your protocol declaration to:

@protocol MyViewControllerlDelegate<NSObject>

Other than that, things are looking good.

Set a generic class as a delegate in swift

When my XMLUtil class is a generic class

But Objective-C knows nothing of generic classes. So there is no way to show your XMLUtil class to Objective-C. Thus, it cannot serve as NSXMLParser's delegate; NSXMLParser is an Objective-C class and cannot see your XMLUtil class if it is generic.

One easy way to see this is to try to mark your XMLUtil class as @objc. You will fail; the compiler will stop you. There is no way to show this class to Objective-C.

UITableView with controller separate from ViewController

Your issue is being caused by a memory management problem. You have the following code:

override func viewDidLoad() {
super.viewDidLoad()
var viewController = StateViewController()
self.stateTableView.delegate = viewController
self.stateTableView.dataSource = viewController
}

Think about the lifetime of the viewController variable. It ends when the end of viewDidLoad is reached. And since a table view's dataSource and delegate properties are weak, there is no strong reference to keep your StateViewController alive once viewDidLoad ends. The result, due to the weak references, is that the dataSource and delegate properties of the table view revert back to nil after the end of viewDidLoad is reached.

The solution is to create a strong reference to your StateViewController. Do this by adding a property to your view controller class:

class ViewController: UIViewController{
@IBOutlet var stateTableView: UITableView!
let viewController = StateViewController()

override func viewDidLoad() {
super.viewDidLoad()

self.stateTableView.delegate = viewController
self.stateTableView.dataSource = viewController
}
}

Now your code will work.

Once you get that working, review the answer by Ahmed F. There is absolutely no reason why your StateViewController class should be a view controller. It's not a view controller in any sense. It's simply a class that implements the table view data source and delegate methods.



Related Topics



Leave a reply



Submit