segment-appsflyer-ios icon indicating copy to clipboard operation
segment-appsflyer-ios copied to clipboard

SEGContext overwrites UIViewRepresentableContext

Open Paul-Svetlichny opened this issue 5 years ago • 7 comments

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.

Paul-Svetlichny avatar Dec 23 '20 08:12 Paul-Svetlichny

Hi @Paul-Svetlichny,

SEGContext file is not part of AppsFlyer repo, but rather Segment repo. I would suggest checking directly with them!

af-margot avatar Dec 23 '20 12:12 af-margot

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.

bsneed avatar Jan 12 '21 22:01 bsneed

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.

af-margot avatar Jan 31 '21 09:01 af-margot

I am able to reproduce this (cc @af-margot @bsneed) :

  1. Create new Xcode project based on SwiftUI
  2. Create new UIViewRepresentable object (replace ContentView with example below)
  3. Follow instructions for adding bridging header
  4. 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()
    }
}

mikebernardo avatar Feb 28 '21 14:02 mikebernardo

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) {}

bsneed avatar Mar 03 '21 19:03 bsneed

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) {}

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) {}

xcodedave avatar Oct 07 '22 13:10 xcodedave

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.

xcodedave avatar Oct 07 '22 13:10 xcodedave