Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Xcode 7.3 undeclared type for Obj C enum in Swift code

Tags:

swift

xcode7.3

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.

like image 240
Fawkes Avatar asked Mar 24 '16 14:03

Fawkes


2 Answers

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.

like image 179
Fawkes Avatar answered Oct 23 '22 06:10

Fawkes


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?

like image 33
John Difool Avatar answered Oct 23 '22 06:10

John Difool