45

I have a main class, also providing a namespace:

class A {
}

and a nested class added via an extension (all for the sake of using separate files):

extension A {
  class B {
  }
}

I want to add functionality to the nested class (B) by extending it; I've tried:

extension A.B {
}

I get "'B' is not a member type of 'A'".

(I've also tried some less reasonable things but I will omit them here to avoid embarrassment. Reading Swift docs and Googling for "swift nested class extension" have not yielded an answer either.)

Any idea if and how that could be accomplished?


UPDATE:

This code works as expected when in a single file (or in a Playground), thanks to user3441734 for trying it out!

Still does not work when the 3 parts are in separate files, perhaps a bug in current implementation of the Swift compiler. I will submit a bug report to Apple.

Baglan
  • 1,057
  • 10
  • 23
  • Which version of Xcode/Swift are you using? – Martin Delille Jul 18 '16 at 18:58
  • Hi Martin. To be clear, each of the definitions is in a separate file. That being the case, I've just managed to reproduce the issue in Xcode 7.3.1 with Swift 2.2. If you put all the definitions in one file (as was the case with the playground in answers below), everything works fine. In other words, this is not a issue with Swift as such, but with the compiler. – Baglan Jul 20 '16 at 04:36

2 Answers2

92

It seems like this problem is related to SR-631. I've encountered similar a issue, I guess the complier is trying to process the file where you extend the nested class before the one where it's defined. Therefore you have this error saying that that A has no member B.

The solution I've found is to go to your target settings, open Build Phases.

enter image description here

There, in Compile Sources section you should put the file where you define the nested class above files where you extend it.

Update

The fix will be shipping with Xcode 10.2

Nikita Kukushkin
  • 14,648
  • 4
  • 37
  • 45
  • 12
    Thank you for the answer! The fact that the ordering of the sources solves the problem probably means that there is a certain number of passes compiler takes when resolving symbols and this case is beyond this number. I've submitted a bug report to Apple and, hopefully, they will do something about it in a future version of Xcode. – Baglan Apr 14 '16 at 02:51
  • 1
    Is there a way to also fix this when using the swift compiler through the command line interface? – Evert Jan 02 '17 at 14:21
  • @cnotethegr8 Pods recreates the Xcode project and add them to the Compile Source list in alphabetically order... – Jonathan. Jan 28 '19 at 14:19
  • Thank you for this. – funct7 Mar 20 '19 at 05:50
3

this works in my playground, as expected

class A {
}
extension A {
    class B {
    }
}
extension A.B {
    func foo() {
        print("print from extension A.B")
    }
}
let ab = A.B()
ab.foo()    // print from extension A.B
user3441734
  • 16,722
  • 2
  • 40
  • 59
  • Indeed it does. The, I assume, this is a bug in how current implementation of Swift in Xcode processes files. I'll submit a bug report to Apple. Thanks! – Baglan Feb 29 '16 at 04:45