// // DouyinShare.swift // ylgamehall // // 抖音分享 SharePlatform 实现(Phase 4.D 完整)。 // // 移植 msext DouyinShareManager.m:201-269 shareImageToDouyin 流程: // 1. 拿图片源(type=2 → ImageProvider.captureScreenshot;其它 → // ImageProvider.downloadRemote);type=1 链接 → 抖音不原生支持纯链接, // 退化为截屏分享(msext 行为:所有 H5 分享到抖音都走图片) // 2. PhotoLibrarySaver.save 保存到相册(addOnly 权限) // 3. UIPasteboard 兜底放图片数据,供抖音读取 // 4. 按顺序尝试 snssdk1128://camera / publish / share/image / 基础 scheme, // canOpenURL 命中即调起 // 5. 调起即视为 success(URL Scheme 单向无返回) // // **不依赖抖音 SDK**。 // import UIKit import os.log @MainActor public final class DouyinShare: SharePlatform { public static let shared = DouyinShare() private static let log = Logger(subsystem: "ylgamehall", category: "DouyinShare") public let name = "Douyin" public var isInstalled: Bool { guard let url = URL(string: "snssdk1128://") else { return false } return UIApplication.shared.canOpenURL(url) } public init() {} public func share(_ content: ShareContent, scene: ShareScene) async -> ShareResult { guard isInstalled else { return .notInstalled(platform: name) } // 1. 拿图片源 let image: UIImage do { switch content.type { case "2": image = try ImageProvider.captureScreenshot() case "1": // 抖音不支持纯链接分享,退化为当前屏截屏(msext 行为) Self.log.debug("DouyinShare: type=1 链接,退化为截屏分享") image = try ImageProvider.captureScreenshot() default: // type == 其它 → 远端图片 URL image = try await ImageProvider.downloadRemote(content.webpageUrl) } } catch { Self.log.error("DouyinShare: 获取图片失败 \(error.localizedDescription, privacy: .public)") return .failed(reason: "获取图片失败: \(error.localizedDescription)") } // 2. 保存到相册(含权限检查) do { try await PhotoLibrarySaver.save(image) } catch PhotoLibrarySaverError.permissionDenied { Self.log.warning("DouyinShare: 相册写入权限被拒") return .failed(reason: "相册写入权限被拒") } catch { Self.log.error("DouyinShare: 保存相册失败 \(error.localizedDescription, privacy: .public)") return .failed(reason: "保存相册失败: \(error.localizedDescription)") } // 3. 同时放剪贴板兜底(msext 行为:抖音从剪贴板读图) UIPasteboard.general.image = image // 4. 按 msext 顺序尝试多个 URL Scheme let schemes = [ "snssdk1128://camera", // 抖音拍摄界面 "snssdk1128://publish", // 发布界面 "snssdk1128://share/image", // 图片分享(可能已废弃但保留) "snssdk1128://" // 兜底基础 scheme ] for schemeString in schemes { guard let url = URL(string: schemeString), UIApplication.shared.canOpenURL(url) else { continue } Self.log.debug("DouyinShare open: \(schemeString, privacy: .public)") let opened = await UIApplication.shared.open(url) if opened { return .success } } return .failed(reason: "所有抖音 URL Scheme 都调起失败") } }