Skip to content

Support data sharing with App Groups for App Clips #655

@IsaiahJTurner

Description

@IsaiahJTurner

We use App Group and would like to use a shared app group container so our App Clip can have the same identity. Currently, this workaround of swizzling various parts of Persistence seems to work but is not ideal.

public extension URL {
  static var dataDirectory: URL? {
    let appGroupURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Constants.appGroupId)
    let defaultDirectory = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
    return appGroupURL ?? defaultDirectory
  }
}

extension FileManager {
  
  // Swizzled method
  @objc private func swizzled_urls(for directory: FileManager.SearchPathDirectory, in domainMask: FileManager.SearchPathDomainMask) -> [URL] {
    if Thread.callStackSymbols.joined().contains("Mixpanel"), let dataDirectory = URL.dataDirectory {
      return [dataDirectory]
    }
    return swizzled_urls(for: directory, in: domainMask)
  }
  
  static let swizzleURLs: Void = {
    let originalSelector = #selector(FileManager.urls(for:in:))
    let swizzledSelector = #selector(FileManager.swizzled_urls(for:in:))
    
    guard
      let originalMethod = class_getInstanceMethod(FileManager.self, originalSelector),
      let swizzledMethod = class_getInstanceMethod(FileManager.self, swizzledSelector)
    else {
      return
    }
    
    method_exchangeImplementations(originalMethod, swizzledMethod)
  }()
}

public extension UserDefaults {
  static let swizzleSuiteName: Void = {
      let originalSelector = #selector(UserDefaults.init(suiteName:))
    let swizzledSelector = #selector(UserDefaults.init(swizzled_init:))

      guard let originalMethod = class_getInstanceMethod(UserDefaults.self, originalSelector),
            let swizzledMethod = class_getInstanceMethod(UserDefaults.self, swizzledSelector) else {
          return
      }

      method_exchangeImplementations(originalMethod, swizzledMethod)
  }()

  @objc convenience init?(swizzled_init suiteName: String?) {
      if suiteName == "Mixpanel" {
          self.init(suiteName: Constants.appGroupId)
      } else {
          self.init(swizzled_init: suiteName)
      }
  }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions