SEGContext overwrites UIViewRepresentableContext
NS_SWIFT_NAME(Context) @interface SEGContext : NSObject <NSCopying>
This part in the header SEGContext.h overwrites SwiftUI UIViewRepresentable typealias Context = UIViewRepresentableContext<Self>
Leads to application using SwiftUI and UIViewRepresetableContext<Self> as Context building fails.
Hi @Paul-Svetlichny,
SEGContext file is not part of AppsFlyer repo, but rather Segment repo. I would suggest checking directly with them!
Hi, Brandon @ Segment here. We're having customers reporting this issue after upgrading the AppsFlyer SDK recently. AppsFlyer isn't open source so I can't really dig in to see, but it doesn't seem feasible that a class of ours being called "Context" would impact a type alias called "Context", particularly in different modules. The original reporter didn't supply any compiler output, so we don't really have anything to go on. If anyone else views this thread, please share the compiler output and we'll see what we can do on our end or identify what AppsFlyer should do on theirs.
Hi @bsneed , @Paul-Svetlichny, Any new info on this, more people having this issue? We are not able to reproduce the issue on our side. So any info will be helpful.
I am able to reproduce this (cc @af-margot @bsneed) :
- Create new Xcode project based on SwiftUI
- Create new UIViewRepresentable object (replace ContentView with example below)
- Follow instructions for adding bridging header
- Install segment-appsflyer-ios via Cocoapods instructions
Compilation will fail due to conflict with Context type alias in UIViewRepresentable
(Remove the include for SEGAppsFlyerIntegrationFactory.h in the bridging header and then it will compile fine)
//
// ContentView.swift
import SwiftUI
struct ColorWrapper: UIViewRepresentable {
func makeUIView(context: Context) -> UIView {
let view = UIView()
view.backgroundColor = UIColor.red
return view
}
func makeCoordinator() -> Coordinator {
Coordinator()
}
func updateUIView(_ uiView: UIView, context: Context) {}
class Coordinator: NSObject { }
}
struct ContentView: View {
var body: some View {
VStack{
Text("Hello, world!")
.padding()
ColorWrapper()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Oh, I see. You need to prefix Context there with the appropriate namespace. The Context desired in this case is internal to UIViewRepresentable, so it needs to be ...
func updateUIView(_ uiView: UIView, context: UIViewRepresentable.Context) {}
Oh, I see. You need to prefix Context there with the appropriate namespace. The
Contextdesired in this case is internal to UIViewRepresentable, so it needs to be ...func updateUIView(_ uiView: UIView, context: UIViewRepresentable.Context) {}
This is not quite correct as Context is generic and inferred from the concrete type conforming to UIViewRepresentable, so for the above code snippet it'd be:
func makeUIView(context: Self.Context) -> UIView {
let view = UIView()
view.backgroundColor = UIColor.red
return view
}
func updateUIView(_ uiView: UIView, context: Self.Context) {}
AppsFlyer isn't open source so I can't really dig in to see, but it doesn't seem feasible that a class of ours being called "Context" would impact a type alias called "Context", particularly in different modules.
Only Swift modules namepsace their symbols at the module level. Obj-C does not have the concept of modular namespacing (see: https://clang.llvm.org/docs/Modules.html#id12), and the Objective-C namespace is global.
Unfortunately I think this line exposing the Obj-C type via NS_SWIFT_NAME macro is causing the type name Context to collide globally: https://github.com/segmentio/analytics-ios/blob/master/Segment/Classes/SEGContext.h#L51
I think it'd be a huge help to all SwiftUI developers to avoid renaming the type exposed to Swift to avoid such a common collision.