Making Protocol Buffer objective c headers public in a Swift Framework

Hey everyone,

I'm running into a very specific case right now and I'm wondering if anyone
has any experience with this situation.

I have a Swift project that is using a custom Swift framework that I
created. The Swift framework contains a bunch of public objects that can be
used by the projects that import this framework.

I now want to change those public objects to be defined and generated by
Google Protocol Buffers. Currently, Google's supported languages only has
Objective-C and not Swift for iOS classes so I have generated a bunch of
Objective-C classes. This is where the problem comes in.

If I want to use the Objective-C classes in Swift inside and outside of the
Framework, I need to include the generated class headers into the
framework's umbrella header. In Xcode 7.1 and above, the Swift compiler has
become very strict and will not accept non-modular headers. I've made all
the generated classes public but their imported classes all need to be
public as well which also need to be made public, and since this is the
protobuf Framework, this is made much harder.

eg. #import "GPBProtocolBuffers.h" //This has to be made public and
everything GPBProtocolBuffers.h has to be modular etc.

I need my generated Objective-C classes to be made public and accessible to
everything that imports that framework I've created. Has anyone come across
this before and have a reasonable solution?

Summary:

   - Have a Swift project using a Swift framework's public objects.
   - Changed the framework's objects to Google Protocol Buffer generated
   Objective-C classes.
   - The Objective-C classes have to be added to the umbrella header so
   Swift can access them.
   - Swift compiler complains about inclusion of non-modular classes.

Thanks,

Vic

Hi, Victor. The particular things I'd look at are

- Make sure the protobuf-generated headers end up in the final "Headers" folder of your framework. (You may need to add a custom "Copy Headers" build phase, not sure.)
- Make sure your all #imports use the angle-bracket style: <MyFramework/GPBProtocolBuffers.h> rather than "GPBProtocolBuffers.h".
- Make sure your umbrella header imports all of the generated headers you want to be visible from Swift. (You can also do this with a custom module map, but this way is simpler.)

I'm guessing it's #2 that might be some trouble. I'm afraid any issue there might have to be taken up with the ObjC protobuf folks.

Hope that helps,
Jordan

P.S. The related problem of "this should just be an implementation detail of my framework; why is it in my umbrella header?" is something we know is an issue, but which needs a bit of design work to get right. (Both the compiler and the debugger need to know what they can and can't assume about a framework.)

···

On Jan 25, 2016, at 15:14, Victor Leong via swift-users <swift-users@swift.org> wrote:

Hey everyone,

I'm running into a very specific case right now and I'm wondering if anyone has any experience with this situation.

I have a Swift project that is using a custom Swift framework that I created. The Swift framework contains a bunch of public objects that can be used by the projects that import this framework.

I now want to change those public objects to be defined and generated by Google Protocol Buffers. Currently, Google's supported languages only has Objective-C and not Swift for iOS classes so I have generated a bunch of Objective-C classes. This is where the problem comes in.

If I want to use the Objective-C classes in Swift inside and outside of the Framework, I need to include the generated class headers into the framework's umbrella header. In Xcode 7.1 and above, the Swift compiler has become very strict and will not accept non-modular headers. I've made all the generated classes public but their imported classes all need to be public as well which also need to be made public, and since this is the protobuf Framework, this is made much harder.

eg. import "GPBProtocolBuffers.h" //This has to be made public and everything GPBProtocolBuffers.h has to be modular etc.

I need my generated Objective-C classes to be made public and accessible to everything that imports that framework I've created. Has anyone come across this before and have a reasonable solution?

Summary:
  • Have a Swift project using a Swift framework's public objects.
  • Changed the framework's objects to Google Protocol Buffer generated Objective-C classes.
  • The Objective-C classes have to be added to the umbrella header so Swift can access them.
  • Swift compiler complains about inclusion of non-modular classes.

Thanks,
Vic
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

Hi Jordan,

Thanks for the response.

I think #2 is the big one here. It includes the .h files in the generation.

For #1 and #3, I have the generated headers in a public scope and imported
in the umbrella headers but unfortunately that would mean all the base
protocol buffer headers such as GPBProtocolBuffers.h and all headers that
imports need to be public and included in the umbrella header which doesn't
make sense because I don't want to expose the base Protocol Buffer headers,
only the DTO objects I have generated. I think I have just hit a very
specific case here where I'm trying to use inflexible, generated
objective-c headers in a Swift Framework.

Thanks,
Vic

···

On Tue, Jan 26, 2016 at 6:14 PM, Jordan Rose <jordan_rose@apple.com> wrote:

Hi, Victor. The particular things I'd look at are

- Make sure the protobuf-generated headers end up in the final "Headers"
folder of your framework. (You may need to add a custom "Copy Headers"
build phase, not sure.)
- Make sure your all #imports use the angle-bracket style:
<MyFramework/GPBProtocolBuffers.h> rather than "GPBProtocolBuffers.h".
- Make sure your umbrella header imports all of the generated headers you
want to be visible from Swift. (You can also do this with a *custom
module map,* but this way is simpler.)

I'm guessing it's #2 that might be some trouble. I'm afraid any issue
there might have to be taken up with the ObjC protobuf folks.

Hope that helps,
Jordan

P.S. The related problem of "this should just be an implementation detail
of my framework; why is it in my umbrella header?" is something we know is
an issue, but which needs a bit of design work to get right. (Both the
compiler and the debugger need to know what they can and can't assume about
a framework.)

On Jan 25, 2016, at 15:14, Victor Leong via swift-users < > swift-users@swift.org> wrote:

Hey everyone,

I'm running into a very specific case right now and I'm wondering if
anyone has any experience with this situation.

I have a Swift project that is using a custom Swift framework that I
created. The Swift framework contains a bunch of public objects that can be
used by the projects that import this framework.

I now want to change those public objects to be defined and generated by
Google Protocol Buffers. Currently, Google's supported languages only has
Objective-C and not Swift for iOS classes so I have generated a bunch of
Objective-C classes. This is where the problem comes in.

If I want to use the Objective-C classes in Swift inside and outside of
the Framework, I need to include the generated class headers into the
framework's umbrella header. In Xcode 7.1 and above, the Swift compiler has
become very strict and will not accept non-modular headers. I've made all
the generated classes public but their imported classes all need to be
public as well which also need to be made public, and since this is the
protobuf Framework, this is made much harder.

eg. import "GPBProtocolBuffers.h" //This has to be made public and
everything GPBProtocolBuffers.h has to be modular etc.

I need my generated Objective-C classes to be made public and accessible
to everything that imports that framework I've created. Has anyone come
across this before and have a reasonable solution?

Summary:
• Have a Swift project using a Swift framework's public objects.
• Changed the framework's objects to Google Protocol Buffer generated
Objective-C classes.
• The Objective-C classes have to be added to the umbrella header so Swift
can access them.
• Swift compiler complains about inclusion of non-modular classes.

Thanks,
Vic
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users

--
Thanks,
*Victor Leong *|* Software Developer*
victor.leong@visiercorp.com