22

We have a big issue with the current Xcode version (10.2).

There is a BasicViewController class with the following signature:

class BasicViewController: UIViewController, UITableViewDataSource, UITableViewDelegate

Then we have another class like ExampleViewController: BasicViewController which has some additional logic.

Now comes the tricky part...

We build and run the app on different simulators and devices and everything works properly. Then we archive the app and suddenly didSelectRow is not fired anymore. Deep clean and clean of the project allowed us to reproduce the issue without the need to archive again.

I cannot think of any case when this could happen. And it gets even worse, because I found more similar issues with UITableViewDelegate methods not being called in the child class only when running the archived app. Could it be an issue with some of the optimisations during archiving and submitting the app?

I verify that we set the dataSource and delegate of the table properly, there are no gesture recognisers over the table. The same logic works well after running the app second/third time, but fails first time after a deep clean of the project.

We made a test and set the UITableViewDataSource and UITableViewDelegate in the child class and then it works as expected every time. It seems inheriting the protocols does not work well. If we keep the protocols in the parent and also add them in the child class, then it says that the protocols in the child class are redundant.

Has anyone experienced anything similar? Any suggestions are welcome.

o15a3d4l11s2
  • 3,969
  • 3
  • 29
  • 40
  • So do you have problem with protocol inheritance or with didSelectRow function? – Niki Apr 09 '19 at 12:00
  • @nTri, didSelectRow is not fired, and as I described in my tests it seems to be related to the protocol of didSelectRow (UITableViewDelegate) being in the parent class. As I describe, it is a very strange behaviour, so I tried to put all my thoughts and tests inside the description. – o15a3d4l11s2 Apr 09 '19 at 12:11
  • 1
    Does the same code still work from Xcode 10.1? You should try creating a test project and see if the same issue occurs using Xcode 10.2 in that project as well. – Dávid Pásztor Apr 09 '19 at 12:28
  • @DávidPásztor, seems to be related to Xcode 10.2 explicitly. – o15a3d4l11s2 Apr 09 '19 at 18:02
  • We've got what seems to be a very, very similar problem - but not sure it's exactly the same. We've made a post here: https://stackoverflow.com/questions/56009500/basic-inheritance-breaking-in-xcode-10-2-with-swift-5-compiler – GPRyan May 06 '19 at 17:03

3 Answers3

15

You may be running into https://bugs.swift.org/browse/SR-10257 in the Swift 5.0 compiler. This would happen if you have at least three files:

  1. BasicViewController.swift
  2. SomeOtherFile.swift
  3. ExampleViewController.swift

If SomeOtherFile.swift makes any calls to an AnyObject-typed value, you're compiling in wholemodule mode, and the files are passed to the compiler in the above order (with SomeOtherFile.swift in the middle of the two), then it seems that the compiler fails to properly infer @objc-ness for the implementation of func tableView(_:, didSelectRowAt:). You can work around it by explicitly tagging it with @objc for now.

BJ Homer
  • 48,806
  • 11
  • 116
  • 129
  • This seems like a great suggestion. Unfortunately at the moment we are still using Swift 4.2. Could the same issue apply to Swift 4.2? – o15a3d4l11s2 Apr 09 '19 at 12:51
  • 1
    Yes; if you're using Xcode 10.2, you're using the Swift 5.0 compiler, even if you're using it in the "Swift 4.2 language" mode. – BJ Homer Apr 09 '19 at 13:01
  • 2
    Instead of marking it `@objc`, could it be easier to switch off `wholemodule` optimisation? – o15a3d4l11s2 Apr 09 '19 at 13:06
  • 3
    Yes, you could do that, though turning off `wholemodule` can have performance implications. You can also work around it by just removing `Basic` and `Example` from the Xcode target and then adding them again, which will cause them to be passed to the compiler in a different order. – BJ Homer Apr 09 '19 at 13:13
  • Hope to worry you for a last time... as we have multiple such files it seems the safest solution would be to use Xcode 10.1 to archive the app? – o15a3d4l11s2 Apr 09 '19 at 13:24
  • 2
    I saw the same issue moving to 10.2 with `CBPeripheralDelegate`. Adding an explicit `@objc` resolved the issue. It wasn't resolving one of the optional methods correctly. – Rob Napier Apr 09 '19 at 14:02
  • 4
    Interesting bug (or feature :P)... Weird it has priority medium, since this can break lots of applications – J. Doe Apr 09 '19 at 14:38
  • 2
    I added @objc, But still its not working, Any one can help me. – Vasanthan Prem May 25 '19 at 08:39
  • Solution doesn't work in case ExampleViewController is a generic – Skie Jun 07 '19 at 14:33
2

I ran into the same issue. I fixed it by adding the methods directly in my main class, and override them in the other classes. Now everything gets called correctly.

J. Doe
  • 12,159
  • 9
  • 60
  • 114
-5

You should attached dataSource and delegate both side using Storyboard and also Class, because once i had the same issue for tableview and it was due to in class i have not done

self.tableView.delegate = self
self.tableView.datasource = self

i think you are not doing like this.

I know that it's not necessary to use both style but some time we need this. have a look on this answer https://stackoverflow.com/a/39443079/3485420