Implementing Protocol In Generic class in swift - ios

Let say I want to make Class TableViewDataSourceImpl like this :
class TableViewDataSourceImpl<T, U: UITableViewCell where U: ReusableCell>:NSObject, UITableViewDataSource {
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
}
}
then xcode show me error type 'TableViewDataSource<T,U>' does not conform to protocol 'UITableViewDataSource'
is this a bug in xcode? or swift cannot make class with generic that implement protocol? because I gonna make tableView.datasource = tableViewDataSource
i know that we cant convert our swift generic into objective-c, but I not gonna use any objective-c here
I do this in xcode 7 beta 1

just update my xcode to beta 2 and it works!

Related

Cannot adopt UITableViewDataSource protocol - Method does not override any method from its superclass

I'm playing around with the UITableView in XCode 10.2.1 with Swift 5. According to the Apple Developer docs, adopting the UITableViewDataSource is the most straightforward way to populate a UITableView with dynamic data.
So I copied the necessary methods to override into a custom class:
import Foundation
import UIKit
class MyDataSource : NSObject, UITableViewDataSource {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 10
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// Fetch a cell of the appropriate type.
let cell = tableView.dequeueReusableCell(withIdentifier: "cellTypeIdentifier", for: indexPath)
// Configure the cell’s contents.
cell.textLabel!.text = "Cell text"
return cell
}
}
But my code won't compile. All I get is a "Method does not override any method from its superclass" error. What? I even did used the autocomplete feature from XCode and it generated the stubs for me, yet I still cannot build my project. What is the solution?
Your class' superclass is NSObject which does not have those table view data source methods to override in a subclass. I believe that is what that compiler is saying.
I think if you take off the override keyword on those function declarations that could help.

Make an extensions of generic class in Swift4

Lets assume we have a simple generic class:
class Foo<T> {
}
next add to this class an extension which implements UITableViewDatasoure:
extension Foo: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//Code here
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//Code here
}
}
This construction causes a compiler error with message:
#objc is not supported within extensions of generic classes or classes
that inherit from generic classes Non-'#objc' method
'tableView(_:numberOfRowsInSection:)' does not satisfy requirement of
'#objc' protocol 'UITableViewDataSource'
Anyone can tell me why? And how to fix that?
The error message seems very clear. This isn't supported. You can't attach an #objc method to a generic class in an extension. You need to define these methods in the class definition, not an extension. The "why" is "the compiler doesn't support it today." (It's likely hard to support because of specializations, but the real answer is "the compiler can't do it.")
Currently the Xcode doesn't support attach an #objc method to a generic class in an extension, you can fix it by define the method inside the class definition, as following:
class Foo<T>: UIViewController, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//Code here ...
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//Code here ...
}
}

Type UiViewController does not conform to protocol xxx

I have a delegate method in Objective-C code which need to implement in my project which was earlier in swift 2.3 and worked fine but after upgrading to swift 3.0 it shows error...
Type UiViewController does not conform to protocol xxx
I have tried everything I can think of but it still isn't working.
function in protocol from Objective-C like UITableViewDataSouce has changed to a more swift style
eg:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
has change to
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
just modify to new styled func,the error will be gone

Swift 3 ObjC Optional Protocol Method Not Called in Subclass

I have the following class hierarchy:
class ScrollableViewController: UIViewController, UITableViewDelegate { // ... }
That implements one UITableViewDelegate protocol method, e.g. tableView:willDisplayCellAt:
In my class SpecificScrollableViewController, which inherits from ScrollableViewController, new optional protocol methods don't get called any more, e.g. tableView(_:heightForRowAt:)
tl;dr you need to prefix the function declaration with its Objective-C declaration, e.g.
#objc(tableView:heightForRowAtIndexPath:)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// return stuff
}
I was tipped off to this being a solution thanks to the Swift 3 Migration Guide which states:
If you implement an optional Objective-C protocol requirement in a subclass of a class that declares conformance, you’ll see a warning, “Instance method ‘…’ nearly matches optional requirement ‘…’ of protocol ‘…’”
• Workaround: Add an #objc(objectiveC:name:) attribute before the implementation of the optional requirement with the original Objective-C selector inside.
I'm fairly certain this is a bug: it appears that the the runtime dynamism that allows checking for selector capability does not get properly bridged in the Grand Swift Renaming when the protocol method is in the subclass. Prefixing the function declaration with the Objective-C name properly bridges the Swift to Objective-C and allows Swift 3 renamed methods to be queried with canPerformAction:withSender: from within Objective-C
This appears to be fixed in Swift 3.0.1 for normal subclasses, but is not fixed for generic subclasses:
class A: NSObject, UITableViewDelegate {}
class B: A {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {}
}
class C<T>: A {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {}
}
print(#selector(B.tableView(_:didSelectRowAt:))) // tableView:didSelectRowAtIndexPath:
print(#selector(C<Int>.tableView(_:didSelectRowAt:))) // tableView:didSelectRowAt:
See: https://bugs.swift.org/browse/SR-2817
To fix it: https://stackoverflow.com/a/39416386/1109892
#objc(tableView:heightForRowAtIndexPath:)
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// return stuff
}

Type 'ProfilesTableViewController' does not conform to protocol 'UITableViewDataSource' in Xcode 6 GM seed

Today I migrated to Xcode 6 GM seed and now I get the following error:
Type 'ProfilesTableViewController' does not conform to protocol
'UITableViewDataSource'.
I've overrided numberOfRowsInSection, cellForRowAtIndexPath and numberOfSectionsInTableView. In fact everything worked fine till today. I noticed that when I remove UITableViewDataSource everything is working fine, and no errors occured. So .. Is it necessary to use 'UITableViewDataSource' anymore, or just override the functions from it?
This code compiles fine:
class ProfileTableViewController: UITableViewController, UITableViewDelegate, UITableViewDataSource {
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: UITableViewCell = tableView.dequeueReusableCellWithIdentifier("foo", forIndexPath: indexPath) as UITableViewCell
return cell
}
}
So, you can definitely subclass UITableViewController and define its UITableViewDataSource protocol implementation.
Take notice that I am using the override keyword and also that I am not using auto-unwrapped arguments -- i.e., not like this:
override func tableView(tableView: UITableView!, numberOfRowsInSection section: Int) -> Int {
which was correct in previous Xcode 6 betas.
My guess is that you're not implementing all the required methods, based on the error, at least.
EDIT: Because of the Xcode 6 beta syntax:
override func tableView(tableView: UITableView!, didSelectRowAtIndexPath indexPath: NSIndexPath!){
We had to check the unwrapped tableView. So I used:
if let tblView = tableView {
//code
}
and
if let theIndexPath = indexPath {
//code
}
So ... in order not to change my entire project, I overrided the functions like this:
override func tableView(tableView: UITableView?, didSelectRowAtIndexPath indexPath: NSIndexPath?){
and everything worked fine, except that with my changes the ProfileTableViewController doesn't conform UITableViewDataSource, and I've had to remove the data source from the class definition.

Resources