Xcode 7.3 undeclared type for Obj C enum in Swift code
Asked Answered
K

2

5

In my project I have Swift extensions over Objective C enums, which worked brilliantly in Xcode 7.2.

But with Xcode 7.3 it fails with "undeclared type" in the Swift file where I extend the Obj C enum.

I've built a sample project and it compiles and works well, but I can't make the existing project accept the extension over the Obj C enum.

UPDATE:

After reinstalling Xcode 7.2 I can confirm that the project compiles and builds successfully.

After it worked in Xcode 7.2, I tried launching this project again in Xcode 7.3 and again the same issue -> the Swift extension over Obj C enums can't be build.

After cleaning and deleting the derived data in Xcode 7.3 I receive also the -Swift.h header missing error because the Swift classes haven't been compiled so a header wasn't created yet.

Code explanation:

My Obj C enum inside "FriendRequestResult.h":

typedef NS_ENUM(NSInteger, FriendStatus)
{
    FriendStatusRequestedByUser = 1,
    FriendStatusRequestedByOtherUser,
    FriendStatusFriends,
    FriendStatusBlocked,
    FriendStatusNone,
    FriendStatusError,
};

Now, as expected in my AppName-Bridging-Header.h I have:

#import "FriendRequestResult.h"

Then, I have the swift extension over the FriendStatus which builds in Xcode 7.2, but fails with "use of undeclared type" in Xcode 7.3:

extension FriendStatus
{
    init(stringValue : String?)
    {
        if let stringValue = stringValue
        {
            switch stringValue
            {
                case "REQUESTED_BY_USER": self = .RequestedByUser
                case "REQUESTED_BY_OTHER": self = .RequestedByOtherUser
                case "FRIENDS": self = .Friends
                case "BLOCKED": self = .Blocked
                default: self = .None
            }
        }
        else
        {
            self = .None
        }
    }
}

Actually this extension over the enum has also some other helper functions, but that should not change the problem in any way.

Of course if the extension of the enum gives the undeclared type, then using this type fails everywhere in the Swift code with the same "undeclared things". Basically the enum is not visible at all for the Swift part of the project, even though the import is made in the bridging header.

This question was substantially edited from its first version.

Kagu answered 24/3, 2016 at 14:37 Comment(7)
Do you mind sharing some code sample?Ellord
@JohnDifool, I'll try.. but it seems complex in this situation to be sure that you shared the right parts.Kagu
I created a new hybrid project with your typedef NS_ENUM(NSInteger, FriendStatus) in an Objective-C header file and your extension FriendStatus in a Swift file. It compiles just fine. Can you tell me how to get the error?Riddance
Unfortunately I don't know what exactly causes the problem. As mentioned in the question, I also managed to do a new sample which works. If I would know what exactly creates the "undefined" for the Obj C enum in Swift code, I would maybe be able to solve it. If there would just be a directive like @class in Objective C through which you can promise the compiler that a specific type exists... Because I suppose it just haven't managed yet to get to the Obj C part of the code when it tries to compile the swift extension [even though in the sample it works.. I know]Kagu
Well, I'd say just make a new project, migrate everything into it, and you're all set. No?Riddance
Is there a easy way to migrate 1k+ files? :)Kagu
I can also stick with the Xcode 7.2 for this period :) but there is something that gets done the wrong way and I want to understand what's the issue.Kagu
K
9

Solution 1: Moved the enum in a seaparate header file.

My enum declaration was in the same header as a class header and specifically it was between the @interface and @end of that class.

In Xcode 7.2 it was creating no issues and the parsing of the header was successful, while in Xcode 7.3 they probably optimised something and changed the way it's parsed, so it was seeing my class, but not the enum inside it [maybe it declares it as private if it's inside a class declaration]

Solution 2: Moved the enum declaration outside the @interface @end scope.

Kagu answered 24/3, 2016 at 18:46 Comment(0)
E
1

To answer your question: "Can I somehow force Xcode to generate the Swift header first? Or can I force Xcode to believe that my enums exist somewhere and that it should validate my extensions?"

I found 2 ways to order file compilation.

  1. Using a target and making it a dependency of your project.
  2. Opening the project.pbxproj file and editing the list manually.

Depending on the level of risk and complexity you are ready to tackle, pick one or the other.

I just tried extending an ENUM and things are working fine here. One issue I had in the past was understanding the name stripping convention between Obj-C and Swift but this doesn't look like the issue you are running into. The other issue I encounter invariably is maintaining the @#$% Bridging-Header.h file all the time. Are you positive this is up-to-date?

Ellord answered 24/3, 2016 at 17:14 Comment(8)
Unfortunately, I think I'll have to reformulate the question. From my further research it seems as extensions over Obj C enums are not working with Swift 2.2 and Xcode 7.3, but I'm investigating at the moment. Now this does not seem related to the fact that the header is not being generated, but rather that the Obj C enums maybe are represented differently now in the Swift header than before [with Swift 2.2 and Xcode 7.3]Kagu
Go back to the basic and try to build from scratch a simple example. That's what I just did and to confirm, things are working as they should. Good luck!Ellord
Yep, just finished my own sample and it works as you also confirmed it.Kagu
I am very happy for you.Ellord
These things happen :-) Care sharing? I may use the insight at a later stage.Ellord
See my answer below :)Kagu
Tnx for your support and sorry for misleading initially. But it took some time to get what was actually happening.Kagu
No worries. It's always nice to read when someone figure things out. I wish that person was me more often :-) And btw my test case was indeed separating the ENUM declaration in its own header file (since the project was trivial enough to allow it.)Ellord

© 2022 - 2024 — McMap. All rights reserved.