Something really weird is going on after our Swift 3 migration.
We have two view controllers, both of them implement UITableViewDelegate and both of them implement public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
However only in one of them the actual method is called.
If I change in the one that doesn't work public func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) to public func tableView(_ tableView: UITableView, didSelectRowAtIndexPath: IndexPath) (notice the Swift 2.2 signature) then they both work.
Both view controllers are Swift classes, so I am not sure what the heck is going on.
I am pretty sure it might be a Objective-C vs Swift interoperability issue, but our whole project is written in Swift, so that's why it's hard to figure out what is causing this.
Any help is appreciated.
Thank you.
for Swift 3.0, use
override func tableView(_ tableView: UITableView, didSelectRowAt
indexPath: IndexPath){
//your code...
}
I encountered a similar problem. My problem was caused by having a superclass that adopted the UITableViewDelegate and UITableViewDataSource protocols, and then implementing the actual methods in a subclass.
What I gather is that because UITableViewDelegate and UITableViewDataSource are objective-c protocols, they must be adopted directly by the class implementing these functions. Otherwise the Swift function signatures will not be properly mapped to the objective-c function signatures (not sure why this is the case).
In Swift versions prior to 3.0, the underlying objective-c function signatures matched the signatures in the Swift UITableViewDelegate and UITableViewDataSource protocols. Therefore prior to 3.0 it seems to have worked fine to have a superclass adopt these protocols. However as of Swift 3.0 these signatures are no longer a match. It seems that to have the new-style signature properly mapped to the underlying objective-c signature, your class must directly adopt the UITableViewDelegate and UITableViewDataSource protocols.
Therefore in Swift 3.0 and later, if you do not directly adopt the UITableViewDelegate and UITableViewDataSource protocols then your function signatures must match the old-style underlying objective-c signatures in order for your functions to be called correctly.
Related
I have been following VIPER design pattern for my current iOS (Swift) project and i am new on using design pattern on code. I am having trouble to take decision about customizing or configuring a subclass of UITableViewCell. Do i change the cell's on ViewController's ->
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell this delegate method or on my derived UITableViewCell's class instance method's ?? Actually the work is changing cell's IBOutlets like Label, ImageView from Model data
I think you should change your cell inside cell because you're not breaking the encapsulation and can make your IBOutlets private.
Actually you can incapsulate you UITableViewDelegate and UITableViewDataSource realisation in some object. We're creating TableViewAdapter for this. You can find example of TableViewAdapter in my open source VIPER example here.
So I am just getting into the whole tableView thing but I came across a curious observations and have a question:
Why is it that overriding this function in my UITableViewController class
override func numberOfSections(in tableView: UITableView) -> Int
has a descriptive name but the number of rows in the section is determined this way
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
I find the former much more logical and wonder why it is not used consequently for other tableView parameters.
Why are different versions of the function tableView called for most tableView properties, instead of different functions with descriptive names?
I am sure there is a very good reason and would be thankful if someone wiser than me could shed some light on the issue.
So to put it frankly: Compatibility with Objective-C seems to be the reason for this inconsistency.
I'm currently going through a tutorial on UITableView. While learning I'm attempting to understand how the UITableView should be constructed by following Apple's documentation and its programming guides. In the tutorial, the developer places the dequeueReusableCell(withIdentifier:) method inside of the tableView(_:cellForRowAt:) method which belongs to the datasource. As a newcomer after reading Apple's references and guides, I would not have guessed that the dequeueReusableCell(withIdentifier:) method goes inside of the tableView(_:cellForRowAt:) method. As a developer, how do you pick up on subtle things like this? Is it because the tableView(_:cellForRowAt:) method returns a UITableViewCell and may be the best place to do UITableViewCell configurations?
I'd like to gain a better understanding of Apple's references for future projects, thank you in advance for any comments or answers.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ItemCell", for: indexPath)
return cell
}
Using Swift 3, the UITableView's func tableView(_ tableView: UITableView, cellForRowAt indexPath: #autoclosure #escaping IndexPath) -> UITableViewCell is being called. I want to track who's calling this function. As far as I know, this will only be called if there's a need for a cell to display. However, in stacktrace override internal func tableView(_ tableView: UITableView, numberOfRowsInSection section: #autoclosure #escaping Int) -> Int is not called and there is no stacktrace. Could someone advice to where to start digging up? Thanks!
See attached screenshot
By default, you only see the stack trace that contains debug symbols. So you won't see many framework internals here.
To see everything, there is a small button at the bottom of the stack trace window, third position from the right, that will enable also methods without debug symbols:
(In fact, it depends on your Xcode version; in older versions there is some sort of slider which will display more or less details in the stack trace).
As #AndreasOetjen mentioned, this is a normal behavior because the method get's called from a UIKit Framework class. The call-stack in this Framework is hidden by default and can be opt-io by the mentioned buttons.
I am trying to get used to swift language so as usual after learning some basics about it I have started with storyboard and table view.I have dragged table view controller to storyboard
and created class for it and attached to view controller also.
As soon as I uncomment cellForRowAtIndexPath method I get following swift compiler error
Overriding method with selector 'tableView:cellForRowAtIndexPath:' has incompatible type '(UITableView!, NSIndexPath!) -> UITableViewCell!'
I also have included numberOfSectionInTableView and numberOfRowInSection delegate methods.
I don't know what I am doing wrong here.
so can anybody please help me resolve this issue.
Thanks in advance.
replace your function with this :
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell{
}
This will solve your problem.
EDIT:
If you want to use existing function then you can remove all ! from function and your error will gone.