diff --git a/MyQrCode.xcodeproj/project.pbxproj b/MyQrCode.xcodeproj/project.pbxproj index e4ff1b0..785f46f 100644 --- a/MyQrCode.xcodeproj/project.pbxproj +++ b/MyQrCode.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 5817666F2E54497800C1B687 /* QRCode in Frameworks */ = {isa = PBXBuildFile; productRef = 5817666E2E54497800C1B687 /* QRCode */; }; 581766772E544AFF00C1B687 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 581766752E544AEC00C1B687 /* AVFoundation.framework */; }; + 5817667C2E544C0000C1B687 /* FacebookCore in Frameworks */ = {isa = PBXBuildFile; productRef = 5817667B2E544C0000C1B687 /* FacebookCore */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -73,6 +74,7 @@ files = ( 581766772E544AFF00C1B687 /* AVFoundation.framework in Frameworks */, 5817666F2E54497800C1B687 /* QRCode in Frameworks */, + 5817667C2E544C0000C1B687 /* FacebookCore in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -143,6 +145,7 @@ name = MyQrCode; packageProductDependencies = ( 5817666E2E54497800C1B687 /* QRCode */, + 5817667B2E544C0000C1B687 /* FacebookCore */, ); productName = MyQrCode; productReference = 5817662F2E54241200C1B687 /* MyQrCode.app */; @@ -238,6 +241,7 @@ minimizedProjectReferenceProxies = 1; packageReferences = ( 5817666D2E54497800C1B687 /* XCRemoteSwiftPackageReference "qrcode" */, + 5817667A2E544C0000C1B687 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */, ); preferredProjectObjectVersion = 77; productRefGroup = 581766302E54241200C1B687 /* Products */; @@ -318,6 +322,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -372,6 +377,7 @@ MTL_FAST_MATH = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)"; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; }; @@ -382,6 +388,7 @@ buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_ANALYZER_NONNULL = YES; CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; CLANG_CXX_LANGUAGE_STANDARD = "gnu++20"; @@ -429,6 +436,7 @@ MTL_ENABLE_DEBUG_INFO = NO; MTL_FAST_MATH = YES; SDKROOT = iphoneos; + STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_COMPILATION_MODE = wholemodule; VALIDATE_PRODUCT = YES; }; @@ -464,7 +472,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.abe.example.demo.MyQrCode; + PRODUCT_BUNDLE_IDENTIFIER = com.qrcode.scanner.app; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -506,7 +514,7 @@ "@executable_path/Frameworks", ); MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.abe.example.demo.MyQrCode; + PRODUCT_BUNDLE_IDENTIFIER = com.qrcode.scanner.app; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = YES; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -528,7 +536,7 @@ GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.abe.example.demo.MyQrCodeTests; + PRODUCT_BUNDLE_IDENTIFIER = com.qrcode.scanner.app.tests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -550,7 +558,7 @@ GENERATE_INFOPLIST_FILE = YES; IPHONEOS_DEPLOYMENT_TARGET = 26.0; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.abe.example.demo.MyQrCodeTests; + PRODUCT_BUNDLE_IDENTIFIER = com.qrcode.scanner.app.tests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -570,7 +578,7 @@ DEVELOPMENT_TEAM = 6AS7587HX4; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.abe.example.demo.MyQrCodeUITests; + PRODUCT_BUNDLE_IDENTIFIER = com.qrcode.scanner.app.uitests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -590,7 +598,7 @@ DEVELOPMENT_TEAM = 6AS7587HX4; GENERATE_INFOPLIST_FILE = YES; MARKETING_VERSION = 1.0; - PRODUCT_BUNDLE_IDENTIFIER = com.abe.example.demo.MyQrCodeUITests; + PRODUCT_BUNDLE_IDENTIFIER = com.qrcode.scanner.app.uitests; PRODUCT_NAME = "$(TARGET_NAME)"; STRING_CATALOG_GENERATE_SYMBOLS = NO; SWIFT_APPROACHABLE_CONCURRENCY = YES; @@ -652,6 +660,14 @@ minimumVersion = 27.11.0; }; }; + 5817667A2E544C0000C1B687 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */ = { + isa = XCRemoteSwiftPackageReference; + repositoryURL = "https://github.com/facebook/facebook-ios-sdk"; + requirement = { + kind = upToNextMajorVersion; + minimumVersion = 18.0.0; + }; + }; /* End XCRemoteSwiftPackageReference section */ /* Begin XCSwiftPackageProductDependency section */ @@ -660,6 +676,11 @@ package = 5817666D2E54497800C1B687 /* XCRemoteSwiftPackageReference "qrcode" */; productName = QRCode; }; + 5817667B2E544C0000C1B687 /* FacebookCore */ = { + isa = XCSwiftPackageProductDependency; + package = 5817667A2E544C0000C1B687 /* XCRemoteSwiftPackageReference "facebook-ios-sdk" */; + productName = FacebookCore; + }; /* End XCSwiftPackageProductDependency section */ }; rootObject = 581766272E54241200C1B687 /* Project object */; diff --git a/MyQrCode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved b/MyQrCode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved index 28bd417..eeea45b 100644 --- a/MyQrCode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved +++ b/MyQrCode.xcodeproj/project.xcworkspace/xcshareddata/swiftpm/Package.resolved @@ -1,6 +1,15 @@ { - "originHash" : "fd2455af71f8be5e18c9e2dd99f5fea73d2285d99fb343d056d9b2dde36eadc7", + "originHash" : "811332fdf8997a3f6c0c2880856dbcc192f86e3bc4efc8ad2e5c1b28d8a9e89d", "pins" : [ + { + "identity" : "facebook-ios-sdk", + "kind" : "remoteSourceControl", + "location" : "https://github.com/facebook/facebook-ios-sdk", + "state" : { + "revision" : "b28dde427715b45a26ebebf697929f4a81b15e04", + "version" : "18.0.0" + } + }, { "identity" : "qrcode", "kind" : "remoteSourceControl", diff --git a/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist index b80ee3d..76092c1 100644 --- a/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ b/MyQrCode.xcodeproj/xcuserdata/yc.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist @@ -114,6 +114,36 @@ endingLineNumber = "233" landmarkName = "createInputComponent(for:emailConfig:wifiConfig:contactConfig:locationConfig:calendarConfig:socialConfig:phoneConfig:urlConfig:textConfig:)" landmarkType = "7"> + + + + + + + + + + + + + + + + + + diff --git a/MyQrCode/Core/MyQrCodeApp.swift b/MyQrCode/Core/MyQrCodeApp.swift index 147c361..5aea362 100644 --- a/MyQrCode/Core/MyQrCodeApp.swift +++ b/MyQrCode/Core/MyQrCodeApp.swift @@ -6,6 +6,7 @@ // import SwiftUI +import FacebookCore @main struct MyQrCodeApp: App { @@ -14,6 +15,11 @@ struct MyQrCodeApp: App { @StateObject private var memoryMonitor = MemoryMonitor.shared @State private var showLaunchScreen = true + init() { + // 初始化Facebook SDK + FacebookEventManager.shared.configure() + } + var body: some Scene { WindowGroup { ZStack { @@ -35,6 +41,9 @@ struct MyQrCodeApp: App { withAnimation(.easeInOut(duration: 0.5)) { showLaunchScreen = false } + + // 记录应用启动事件 + FacebookEventManager.shared.logAppLaunch() } } } diff --git a/MyQrCode/Docs/FACEBOOK_SDK_INTEGRATION_README.md b/MyQrCode/Docs/FACEBOOK_SDK_INTEGRATION_README.md new file mode 100644 index 0000000..3db7c39 --- /dev/null +++ b/MyQrCode/Docs/FACEBOOK_SDK_INTEGRATION_README.md @@ -0,0 +1,147 @@ +# Facebook SDK 集成说明 + +## 概述 + +本项目已成功集成Facebook SDK,用于跟踪用户行为和收集应用使用数据。 + +## 集成内容 + +### 1. 依赖管理 +- 使用Swift Package Manager添加Facebook SDK +- 包地址:`https://github.com/facebook/facebook-ios-sdk` +- 最低版本:16.0.0 + +### 2. 核心组件 + +#### FacebookEventManager +位置:`MyQrCode/Utils/FacebookEventManager.swift` + +主要功能: +- 初始化Facebook SDK +- 记录各种应用事件 +- 提供统一的事件跟踪接口 + +#### 事件类型 +- **应用启动**: `logAppLaunch()` +- **二维码扫描**: `logQRCodeScan(type:)` +- **二维码生成**: `logQRCodeGeneration(type:)` +- **功能使用**: `logFeatureUsage(feature:)` +- **分享**: `logShare(contentType:)` +- **购买**: `logPurchase(amount:currency:)` + +### 3. 配置要求 + +#### Info.plist配置 +```xml + +FacebookAppID +YOUR_FACEBOOK_APP_ID +FacebookClientToken +YOUR_FACEBOOK_CLIENT_TOKEN +FacebookDisplayName +MyQrCode +FacebookAutoLogAppEventsEnabled + +FacebookAdvertiserIDCollectionEnabled + +``` + +#### 需要替换的值 +- `YOUR_FACEBOOK_APP_ID`: 你的Facebook应用ID +- `YOUR_FACEBOOK_CLIENT_TOKEN`: 你的Facebook客户端令牌 + +### 4. 使用方法 + +#### 初始化 +在`MyQrCodeApp.swift`中自动初始化: +```swift +init() { + // 初始化Facebook SDK + FacebookEventManager.shared.configure() +} +``` + +#### 记录事件 +```swift +// 记录二维码扫描 +FacebookEventManager.shared.logQRCodeScan(type: "QR_CODE") + +// 记录二维码生成 +FacebookEventManager.shared.logQRCodeGeneration(type: "EMAIL") + +// 记录分享 +FacebookEventManager.shared.logShare(contentType: "qr_code") +``` + +### 5. 事件跟踪点 + +#### 自动跟踪 +- **应用启动**: 启动页面消失后自动记录 +- **二维码扫描**: 扫描成功后自动记录 +- **二维码生成**: 创建二维码时自动记录 +- **分享功能**: 使用分享功能时自动记录 + +#### 手动跟踪 +可以在任何需要的地方手动调用事件记录方法。 + +### 6. 隐私设置 + +#### 已禁用的功能 +- `FacebookAutoLogAppEventsEnabled`: false - 禁用自动事件记录 +- `FacebookAdvertiserIDCollectionEnabled`: false - 禁用广告ID收集 + +#### 用户控制 +- 所有事件跟踪都通过代码控制 +- 不收集个人身份信息 +- 只跟踪应用功能使用情况 + +### 7. 测试和调试 + +#### 开发环境 +- 使用测试Facebook应用ID +- 在Facebook开发者控制台查看事件 + +#### 生产环境 +- 使用正式Facebook应用ID +- 确保所有配置正确 + +### 8. 注意事项 + +#### 合规性 +- 确保符合GDPR等隐私法规 +- 在隐私政策中说明数据收集 +- 提供用户选择退出的选项 + +#### 性能 +- 事件记录是异步的,不影响应用性能 +- 网络请求在后台进行 + +#### 错误处理 +- SDK初始化失败不会影响应用功能 +- 事件记录失败会静默处理 + +## 故障排除 + +### 常见问题 + +1. **编译错误**: 检查Facebook SDK是否正确添加 +2. **初始化失败**: 验证Info.plist配置 +3. **事件不记录**: 检查网络连接和Facebook应用配置 + +### 调试步骤 + +1. 检查控制台日志 +2. 验证Facebook应用配置 +3. 测试网络连接 +4. 查看Facebook开发者控制台 + +## 更新和维护 + +### 版本更新 +- 定期更新Facebook SDK到最新版本 +- 关注Facebook开发者博客的更新说明 + +### 功能扩展 +- 可以添加更多自定义事件 +- 支持自定义参数和属性 +- 集成Facebook Analytics获取更详细数据 diff --git a/MyQrCode/Info.plist b/MyQrCode/Info.plist index a120af9..d18f28c 100644 --- a/MyQrCode/Info.plist +++ b/MyQrCode/Info.plist @@ -19,25 +19,9 @@ CFBundleURLTypes - CFBundleURLName - com.abe.example.demo.MyQrCode.phone CFBundleURLSchemes - tel - sms - - - - CFBundleURLName - com.abe.example.demo.MyQrCode.social - CFBundleURLSchemes - - instagram - fb - twitter - whatsapp - viber - spotify + fb2183345158821655 @@ -48,5 +32,15 @@ NSCalendarsWriteOnlyAccessUsageDescription $(PRODUCT_NAME) needs write-only access to calendar to add events + FacebookAppID + 2183345158821655 + FacebookClientToken + edb0aea9c3cb29f03b23b9e7f07aaed8 + FacebookDisplayName + MyQrCode + FacebookAutoLogAppEventsEnabled + + FacebookAdvertiserIDCollectionEnabled + diff --git a/MyQrCode/Utils/FacebookEventManager.swift b/MyQrCode/Utils/FacebookEventManager.swift new file mode 100644 index 0000000..d64980c --- /dev/null +++ b/MyQrCode/Utils/FacebookEventManager.swift @@ -0,0 +1,65 @@ +import Foundation +import FacebookCore + +// MARK: - Facebook事件管理器 +class FacebookEventManager { + + static let shared = FacebookEventManager() + + private init() {} + + // MARK: - 初始化Facebook SDK + func configure() { + // 配置Facebook SDK + FacebookCore.ApplicationDelegate.shared.application( + UIApplication.shared, + didFinishLaunchingWithOptions: nil + ) + + } + + // MARK: - 记录应用启动事件 + func logAppLaunch() { + FacebookCore.AppEvents.shared.logEvent(.completedRegistration) + } + + // MARK: - 记录二维码扫描事件 + func logQRCodeScan(type: String) { + let parameters = [ + FacebookCore.AppEvents.ParameterName.contentType: "qr_code", + FacebookCore.AppEvents.ParameterName.content: type + ] + FacebookCore.AppEvents.shared.logEvent(.viewedContent, parameters: parameters) + } + + // MARK: - 记录二维码生成事件 + func logQRCodeGeneration(type: String) { + let parameters = [ + FacebookCore.AppEvents.ParameterName.contentType: "qr_code_generation", + FacebookCore.AppEvents.ParameterName.content: type + ] + FacebookCore.AppEvents.shared.logEvent(.completedTutorial, parameters: parameters) + } + + // MARK: - 记录功能使用事件 + func logFeatureUsage(feature: String) { + let parameters = [ + FacebookCore.AppEvents.ParameterName.contentType: "feature_usage", + FacebookCore.AppEvents.ParameterName.content: feature + ] + FacebookCore.AppEvents.shared.logEvent(.searched, parameters: parameters) + } + + // MARK: - 记录分享事件 + func logShare(contentType: String) { + let parameters = [ + FacebookCore.AppEvents.ParameterName.contentType: contentType + ] + FacebookCore.AppEvents.shared.logEvent(.completedTutorial, parameters: parameters) + } + + // MARK: - 记录应用内购买事件(如果有的话) + func logPurchase(amount: Double, currency: String = "USD") { + FacebookCore.AppEvents.shared.logPurchase(amount: amount, currency: currency) + } +} diff --git a/MyQrCode/Views/Generator/CreateQRCodeView.swift b/MyQrCode/Views/Generator/CreateQRCodeView.swift index 7fbd00b..e544c5b 100644 --- a/MyQrCode/Views/Generator/CreateQRCodeView.swift +++ b/MyQrCode/Views/Generator/CreateQRCodeView.swift @@ -103,6 +103,12 @@ Button("confirm".localized) { } EmptyView() } ) + .onChange(of: navigateToStyleView) { newValue in + if newValue { + // 记录二维码生成事件 + FacebookEventManager.shared.logQRCodeGeneration(type: selectedQRCodeType.rawValue) + } + } .onAppear { setupInitialFocus() } diff --git a/MyQrCode/Views/History/HistoryView.swift b/MyQrCode/Views/History/HistoryView.swift index 2d09ed7..0b04f59 100644 --- a/MyQrCode/Views/History/HistoryView.swift +++ b/MyQrCode/Views/History/HistoryView.swift @@ -796,6 +796,10 @@ struct HistoryItemRow: View { } } + // 记录Facebook事件 - 分享功能 + let contentType = item.dataType == DataType.qrcode.rawValue ? "qr_code" : "barcode" + FacebookEventManager.shared.logShare(contentType: contentType) + // 获取当前视图控制器并显示分享界面 if let windowScene = UIApplication.shared.connectedScenes.first as? UIWindowScene, let window = windowScene.windows.first, diff --git a/MyQrCode/Views/History/QRCodeDetailView.swift b/MyQrCode/Views/History/QRCodeDetailView.swift index c31e166..1a596c1 100644 --- a/MyQrCode/Views/History/QRCodeDetailView.swift +++ b/MyQrCode/Views/History/QRCodeDetailView.swift @@ -2,6 +2,8 @@ import SwiftUI import CoreData import QRCode import NetworkExtension +import UIKit +import FacebookCore internal import SwiftImageReadWrite struct QRCodeDetailView: View { diff --git a/MyQrCode/Views/Scanner/ScannerView.swift b/MyQrCode/Views/Scanner/ScannerView.swift index 0b3f86b..40a52a6 100644 --- a/MyQrCode/Views/Scanner/ScannerView.swift +++ b/MyQrCode/Views/Scanner/ScannerView.swift @@ -232,6 +232,14 @@ struct ScannerView: View { self.navigateToDetail = true } + // 记录Facebook事件 - 二维码扫描 + if selectedCode.type.lowercased().contains("qr") || + selectedCode.type.lowercased().contains("二维码") || + selectedCode.type.lowercased().contains("data matrix") || + selectedCode.type.lowercased().contains("aztec") { + FacebookEventManager.shared.logQRCodeScan(type: selectedCode.type) + } + // 发送通知(保持向后兼容) let formattedResult = "类型: \(selectedCode.type)\n内容: \(selectedCode.content)" logInfo(" 格式化结果: \(formattedResult)", className: "ScannerView")