Selaa lähdekoodia

Working demo
Open with

open --env FIREBASECI_USE_LATEST_GOOGLEAPPMEASUREMENT --env FIREBASE_SOURCE_FIRESTORE Package.swift

Nick Cooke 10 kuukautta sitten
vanhempi
sitoutus
20b0db9602

+ 37 - 0
FirebaseFirestoreInternalSwift/Sources/Foo.swift

@@ -0,0 +1,37 @@
+//
+//  Foo.swift
+//  Firebase
+//
+//  Created by Nick Cooke on 5/8/25.
+//
+
+import Foundation
+
+// Approach one
+@objc(FIRFoo) public class Foo: NSObject {
+  @objc public func doStuff() {}
+}
+
+
+// Variant Two (probably preferred)
+// This variant allows you to express the type in pure Swift, and then provide
+// a simpler ObjC compatible version to be used by FirestoreInternal
+
+// This type would probably be a struct rather than class in a Swift-only world.
+public struct Int32Value {
+  let value: Int32
+}
+
+@objc(FIRInt32Value)
+@available(swift 1000.0) // Objective-C only API
+public class FIRInt32Value: NSObject {
+  private let swiftImpl: Int32Value
+  
+  init(int: Int32) {
+    self.swiftImpl = .init(value: int)
+  }
+  
+  var value: Int32 {
+    swiftImpl.value
+  }
+}

+ 14 - 0
Firestore/Source/API/FIRFooWrapper.h

@@ -0,0 +1,14 @@
+//
+//  FIRFooWrapper.h
+//  Firebase
+//
+//  Created by Nick Cooke on 5/8/25.
+//
+
+#import <Foundation/Foundation.h>
+
+@interface FIRFooWrapper : NSObject
+
+- (void)doStuff;
+
+@end

+ 28 - 0
Firestore/Source/API/FIRFooWrapper.m

@@ -0,0 +1,28 @@
+//
+//  FIRFooWrapper.m
+//  Firebase
+//
+//  Created by Nick Cooke on 5/8/25.
+//
+
+#import "FIRFooWrapper.h"
+
+@import FirebaseFirestoreInternalSwift;
+
+@interface FIRFooWrapper ()
+// private property. we call through to it's Swift impl
+@property() FIRFoo *foo;
+@end
+
+@implementation FIRFooWrapper
+
+- (instancetype)init {
+  _foo = [[FIRFoo alloc] init];
+}
+
+- (void)doStuff {
+  [self.foo doStuff];
+}
+
+
+@end

+ 6 - 0
Firestore/Source/API/FIRVectorValue.m

@@ -18,10 +18,16 @@
 
 #include "Firestore/Source/Public/FirebaseFirestore/FIRVectorValue.h"
 
+@import FirebaseFirestoreInternalSwift;
+
 NS_ASSUME_NONNULL_BEGIN
 
 @implementation FIRVectorValue
 
+- (void)example {
+  [[[FIRFoo alloc] init] doStuff];
+}
+
 - (instancetype)initWithArray:(NSArray<NSNumber *> *)array {
   if (self = [super init]) {
     _array = [array valueForKey:@"doubleValue"];

+ 12 - 0
Firestore/Source/API/FSTUserDataWriter.mm

@@ -19,6 +19,13 @@
 #include <string>
 #include <utility>
 
+// 💥 Doesnt work!
+//@import FirebaseFirestoreInternalSwift; // Use of '@import' when C++ modules are disabled, consider using -fmodules and -fcxx-modules
+//
+// And we cannot import the generated `-Swift` because  https://github.com/swiftlang/swift-package-manager/issues/7099
+// But, we can import an ObjC file
+#include "Firestore/Source/API/FIRFooWrapper.h"
+
 #include "Firestore/Protos/nanopb/google/firestore/v1/document.nanopb.h"
 #include "Firestore/Source/API/FIRDocumentReference+Internal.h"
 #include "Firestore/Source/API/FIRFieldValue+Internal.h"
@@ -79,6 +86,11 @@ NS_ASSUME_NONNULL_BEGIN
   return self;
 }
 
+- (void)example:(FIRFooWrapper *)fooWrapper {
+  [fooWrapper doStuff];
+  // Calls into ObjC fooWrapper definition, which calls into source-of-truth Swift module
+}
+
 - (id)convertedValue:(const google_firestore_v1_Value &)value {
   switch (GetTypeOrder(value)) {
     case TypeOrder::kMap:

+ 8 - 0
Firestore/Swift/Source/SwiftHeaderWorkaround.swift

@@ -14,6 +14,8 @@
 
 #if SWIFT_PACKAGE
   @_exported import FirebaseFirestoreInternalWrapper
+  // This re-exports the public API from here in the FirebaseFirestore namespace.
+  @_exported import FirebaseFirestoreInternalSwift
 #else
   @_exported import FirebaseFirestoreInternal
 #endif // SWIFT_PACKAGE
@@ -30,3 +32,9 @@
 @objc public extension Firestore {
   static var __no_op: () -> Void { {} }
 }
+
+// Maybe needed, would have to dig deeper.
+@available(*, unavailable)
+@objc public extension Foo {
+  static var __no_op: () -> Void { {} }
+}

+ 3 - 0
Package.swift

@@ -1429,9 +1429,11 @@ func firestoreWrapperTarget() -> Target {
 func firestoreTargets() -> [Target] {
   if ProcessInfo.processInfo.environment["FIREBASE_SOURCE_FIRESTORE"] != nil {
     return [
+      .target(name: "FirebaseFirestoreInternalSwift", path: "FirebaseFirestoreInternalSwift"),
       .target(
         name: "FirebaseFirestoreInternalWrapper",
         dependencies: [
+          "FirebaseFirestoreInternalSwift",
           "FirebaseAppCheckInterop",
           "FirebaseCore",
           "leveldb",
@@ -1503,6 +1505,7 @@ func firestoreTargets() -> [Target] {
           "FirebaseCoreExtension",
           "FirebaseFirestoreInternalWrapper",
           "FirebaseSharedSwift",
+          "FirebaseFirestoreInternalSwift",
         ],
         path: "Firestore",
         exclude: [