移植 msext DouyinShareManager.m:201-269 shareImageToDouyin 完整流程到 Swift。
新增基础设施(Phase 4.F 截图 / 远端图也共用):
Source/Share/ImageProvider.swift:
- captureScreenshot() throws -> UIImage:UIGraphicsImageRenderer 截
keyWindow(含状态栏 + letterbox 黑边 + WebView),与 msext
FuncPublic.getImageWithFullScreenshot 等价
- downloadRemote(_:) async throws -> UIImage:URLSession.data(from:)
下载远端 URL → UIImage 解码
- ImageProviderError 错误分类(noKeyWindow / downloadFailed / decodeFailed /
badURL)
Source/Share/PhotoLibrarySaver.swift:
- save(_:) async throws:使用 PHAccessLevel.addOnly(iOS 14+ 推荐,仅写
相册不读,弹窗更友好)+ PHAssetChangeRequest.creationRequestForAsset
- 自动处理权限三态(authorized/notDetermined 请求 + denied/restricted 抛错)
DouyinShare.share 完整实现:
- 拿图片源:
* type == "2" 截图 / type == "1" 链接(退化为当前屏截屏,msext 行为)
→ ImageProvider.captureScreenshot
* type == 其它(远端图 URL)→ ImageProvider.downloadRemote(webpageUrl)
- PhotoLibrarySaver.save 保存到相册(含 .permissionDenied 错误回 .failed)
- UIPasteboard.general.image = image 兜底(抖音可能从剪贴板读图)
- 按 msext 顺序尝试 4 个 URL Scheme:
snssdk1128://camera / publish / share/image / 基础 scheme
canOpenURL 命中即 await UIApplication.open + 调起即 success
- 全部失败返回 .failed("所有抖音 URL Scheme 都调起失败")
Info.plist 加 NSPhotoLibraryAddUsageDescription("需要将分享内容保存到
相册,以便您在抖音中选取分享"),addOnly 权限弹窗用此文案。
BuildProject 通过
Plan §5 Phase 4.4 勾选
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
76 lines
3.1 KiB
Plaintext
76 lines
3.1 KiB
Plaintext
<?xml version="1.0" encoding="UTF-8"?>
|
||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||
<plist version="1.0">
|
||
<dict>
|
||
<key>UIApplicationSceneManifest</key>
|
||
<dict>
|
||
<key>UIApplicationSupportsMultipleScenes</key>
|
||
<false/>
|
||
<key>UISceneConfigurations</key>
|
||
<dict>
|
||
<key>UIWindowSceneSessionRoleApplication</key>
|
||
<array>
|
||
<dict>
|
||
<key>UISceneConfigurationName</key>
|
||
<string>Default Configuration</string>
|
||
<key>UISceneDelegateClassName</key>
|
||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||
</dict>
|
||
</array>
|
||
</dict>
|
||
</dict>
|
||
<key>NSAppTransportSecurity</key>
|
||
<dict>
|
||
<!-- 企业签 / 超签分发场景,后端域名可能调整(zip CDN / 配置服 / 七牛 / 错误日志
|
||
上报等),白名单维护成本高于安全收益。决策:全局放行,由代码层面通过 HTTPS
|
||
优先 + URLSession session 校验保证非白名单的第三方 SDK 流量自身仍走加密通道。
|
||
详见 ADR-008 / CLAUDE.md「不上架 App Store,通过企业签 / 超签 / TF 分发」。 -->
|
||
<key>NSAllowsArbitraryLoads</key>
|
||
<true/>
|
||
</dict>
|
||
<key>UIRequiresFullScreen</key>
|
||
<true/>
|
||
<key>UIStatusBarHidden</key>
|
||
<false/>
|
||
<key>UIViewControllerBasedStatusBarAppearance</key>
|
||
<true/>
|
||
<!--
|
||
LaunchScreen 阶段(iOS 在 app 进程尚未启动、device idiom 尚未识别的早期窗口)
|
||
只看顶层 UISupportedInterfaceOrientations,不识别 ~iphone / ~ipad 后缀变体。
|
||
Xcode 26 的 General → Deployment Info UI 只会写 INFOPLIST_KEY_*_iPhone /
|
||
INFOPLIST_KEY_*_iPad 两条带后缀的 key,会导致 LaunchScreen 默认 portrait 渲染、
|
||
再被旋转 90° 适配横屏设备(视觉:splash 内容横躺)。在 Info.plist 里显式补一份
|
||
无后缀 key 修复 LaunchScreen orientation。
|
||
-->
|
||
<key>UISupportedInterfaceOrientations</key>
|
||
<array>
|
||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||
</array>
|
||
<!--
|
||
LSApplicationQueriesSchemes — canOpenURL 白名单(iOS 9+ 必须声明,否则
|
||
canOpenURL 总返回 false)。本项目分享接入:
|
||
- QQ(URL Scheme 路径,不依赖 SDK):mqq / mqqapi / mqqopensdkfriend 等
|
||
- 抖音(URL Scheme + Photos 路径,不依赖 SDK):snssdk1128
|
||
- 微信(Phase 4.E SDK 接入时再加 weixin / weixinULAPI / weixinURLParamsAPI)
|
||
-->
|
||
<key>LSApplicationQueriesSchemes</key>
|
||
<array>
|
||
<string>mqq</string>
|
||
<string>mqqapi</string>
|
||
<string>mqqopensdkfriend</string>
|
||
<string>mqqopensdkapiV2</string>
|
||
<string>mqqopensdkapiV3</string>
|
||
<string>mqqopensdkapiV4</string>
|
||
<string>snssdk1128</string>
|
||
</array>
|
||
<!--
|
||
NSPhotoLibraryAddUsageDescription — Phase 4.D 抖音分享需要保存截图 / 远端图
|
||
到相册让用户在抖音 app 里选取(msext DouyinShareManager.m 同款流程)。
|
||
用 addOnly 权限级别(仅写不读),iOS 14+ 弹窗对用户更友好。
|
||
-->
|
||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||
<string>需要将分享内容保存到相册,以便您在抖音中选取分享</string>
|
||
</dict>
|
||
</plist>
|