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
Nstableview Get Indexpath Having the Cell
How to "Explicitly" Implement a Protocol in Swift? If It Is Impossible, Why
Cast to Different C Struct Unsafe Pointer in Swift
Arkit - Collision with Real World Objects
Characters Is Unavailable' Please Use String Directly
How to Prompt for Accessibility Features in a MACos App (From the Appdelegate)
How to Wait for Http Requests to Finish
Swift Realm: After Writing Transaction Reference Set to Nil
Saving Highscores with Nsuserdefaults
Drag a Cgrect Using Uipangesturerecognizer
Play Segment of Avaudiopcmbuffer
Get Compiler Error in Swift Indexof()
Value of Type 'Tags' Has No Member 'Lastused'
Swift Spritekit Arc for Dummies
How to Return a Value from a Void Closure in Swift
Overlapping Accesses to 'Urlcomponents', But Modification Requires Exclusive Access