From 1db4cd1d7302c0bcdf716c4e6897f752dc44bcd5 Mon Sep 17 00:00:00 2001 From: Do-hyun-Kim Date: Thu, 19 Dec 2024 21:11:03 +0900 Subject: [PATCH 1/3] =?UTF-8?q?feat:=20Core=EB=AA=A8=EB=93=88=20=EB=82=B4?= =?UTF-8?q?=EB=B6=80=20BBAnalyticsLogParametable,=20=20BBAnalyticsLogType,?= =?UTF-8?q?=20=20BBEventAnalyticsLog,=20=20BBLogManager=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80=20-=20Tuist=20TuistScript+Templates=20dsym=20Upload?= =?UTF-8?q?=EB=A5=BC=20=ED=95=98=EA=B8=B0=20=EC=9C=84=ED=95=9C=20Script=20?= =?UTF-8?q?=ED=8C=8C=EC=9D=BC=20=EC=B6=94=EA=B0=80=20-=20=EA=B0=81=20ViewC?= =?UTF-8?q?ontroller=EC=97=90=20Analytics=20Event=20log=20=EB=A9=94?= =?UTF-8?q?=EC=84=9C=EB=93=9C=20=EC=B6=94=EA=B0=80=20-=20Crashlytics=20Log?= =?UTF-8?q?=20Method=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../App/Sources/Application/AppDelegate.swift | 1 - .../Navigator/CameraDisplayNavigator.swift | 2 + .../Navigator/CameraNavigator.swift | 1 + .../AccountProfileViewController.swift | 1 + .../MonthlyCalendarViewController.swift | 6 ++ .../Camera/CameraDisplayViewController.swift | 1 + .../Camera/CameraViewController.swift | 1 + .../JoinFamilyViewController.swift | 6 +- .../ViewControllers/MainViewController.swift | 1 + .../FamilyNameSettingViewController.swift | 6 ++ .../ManagementViewController.swift | 6 ++ .../ViewControllers/PostViewController.swift | 1 + .../Privacy/PrivacyViewController.swift | 3 + .../ProfileFeedPageViewController.swift | 15 +++- .../Profile/ProfileViewController.swift | 3 + .../Resign/AccountResignViewController.swift | 2 + .../BBNetwork/Network/BBNetworkError.swift | 25 +++++++ .../Core/Sources/Extensions/String+Ext.swift | 36 ++++++++++ .../Logger/BBAnalyticsLogParametable.swift | 16 +++++ .../Utils/Logger/BBAnalyticsLogType.swift | 38 ++++++++++ .../Utils/Logger/BBEventAnalyticsLog.swift | 66 ++++++++++++++++++ .../Sources/Utils/Logger/BBLogManager.swift | 69 +++++++++++++++++++ .../FamilyUserDefaults.swift | 1 + .../AccountRepository/AccountRepository.swift | 2 +- .../ConfigurationName+Templates.swift | 3 + .../Modular+Templates.swift | 12 +++- .../ModuleType+Templates.swift | 3 +- .../Project+Templates.swift | 2 +- .../TargetScript+Templates.swift | 41 +++++++++++ 29 files changed, 359 insertions(+), 11 deletions(-) create mode 100644 14th-team5-iOS/Core/Sources/Utils/Logger/BBAnalyticsLogParametable.swift create mode 100644 14th-team5-iOS/Core/Sources/Utils/Logger/BBAnalyticsLogType.swift create mode 100644 14th-team5-iOS/Core/Sources/Utils/Logger/BBEventAnalyticsLog.swift create mode 100644 14th-team5-iOS/Core/Sources/Utils/Logger/BBLogManager.swift create mode 100644 Tuist/ProjectDescriptionHelpers/TargetScript+Templates.swift diff --git a/14th-team5-iOS/App/Sources/Application/AppDelegate.swift b/14th-team5-iOS/App/Sources/Application/AppDelegate.swift index 2530fdbca..c74310ea8 100644 --- a/14th-team5-iOS/App/Sources/Application/AppDelegate.swift +++ b/14th-team5-iOS/App/Sources/Application/AppDelegate.swift @@ -13,7 +13,6 @@ import UIKit import AuthenticationServices import Firebase import FirebaseCore -import FirebaseAnalytics import FirebaseMessaging import KakaoSDKAuth import RxKakaoSDKAuth diff --git a/14th-team5-iOS/App/Sources/Application/Navigator/CameraDisplayNavigator.swift b/14th-team5-iOS/App/Sources/Application/Navigator/CameraDisplayNavigator.swift index 32cebdeea..77e557d63 100644 --- a/14th-team5-iOS/App/Sources/Application/Navigator/CameraDisplayNavigator.swift +++ b/14th-team5-iOS/App/Sources/Application/Navigator/CameraDisplayNavigator.swift @@ -29,9 +29,11 @@ final class CameraDisplayNavigator: CameraDisplayNavigatorProtocol { func showErrorAlert() { let confirmHandler: BBAlertActionHandler = { [weak self] alert in self?.toCamera() + BBLogManager.analytics(logType: BBEventAnalyticsLog.clickCameraButton(entry: .failedAlertConfirm)) alert?.close() } let cancelHandler: BBAlertActionHandler = { [weak self] alert in + BBLogManager.analytics(logType: BBEventAnalyticsLog.clickCameraButton(entry: .failedAlertCancle)) self?.toHome() alert?.close() } diff --git a/14th-team5-iOS/App/Sources/Application/Navigator/CameraNavigator.swift b/14th-team5-iOS/App/Sources/Application/Navigator/CameraNavigator.swift index da34040b7..7dc46f7ab 100644 --- a/14th-team5-iOS/App/Sources/Application/Navigator/CameraNavigator.swift +++ b/14th-team5-iOS/App/Sources/Application/Navigator/CameraNavigator.swift @@ -31,6 +31,7 @@ final class CameraNavigator: CameraNavigatorProtocol { func showErrorAlert(_ type: UploadLocation) { let confirmHandler: BBAlertActionHandler = makeConfirmHandler(for: type) let cancelHandler: BBAlertActionHandler = { [weak self] alert in + BBLogManager.analytics(logType: BBEventAnalyticsLog.clickCameraButton(entry: .failedAlertCancle)) self?.toHome() alert?.close() } diff --git a/14th-team5-iOS/App/Sources/Presentation/Account/AccountSignUp/ViewControllers/AccountProfileViewController.swift b/14th-team5-iOS/App/Sources/Presentation/Account/AccountSignUp/ViewControllers/AccountProfileViewController.swift index 34041e43d..aefdcb320 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Account/AccountSignUp/ViewControllers/AccountProfileViewController.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Account/AccountSignUp/ViewControllers/AccountProfileViewController.swift @@ -60,6 +60,7 @@ final class AccountProfileViewController: BaseViewController { public override func viewDidLoad() { super.viewDidLoad() + BBLogManager.analytics(logType: BBEventAnalyticsLog.viewPage(pageName: .camera)) setupCameraPermission() } diff --git a/14th-team5-iOS/App/Sources/Presentation/FamilyEntrance/ViewController/JoinFamilyViewController.swift b/14th-team5-iOS/App/Sources/Presentation/FamilyEntrance/ViewController/JoinFamilyViewController.swift index 88376c15d..ed373ab94 100644 --- a/14th-team5-iOS/App/Sources/Presentation/FamilyEntrance/ViewController/JoinFamilyViewController.swift +++ b/14th-team5-iOS/App/Sources/Presentation/FamilyEntrance/ViewController/JoinFamilyViewController.swift @@ -77,13 +77,17 @@ final class JoinFamilyViewController: BaseViewController { private func bindInput(reactor: JoinFamilyReactor) { makeFamilyButton.rx.tap - .do(onNext: { MPEvent.Account.creatGroup.track(with: nil) }) + .do(onNext: { + MPEvent.Account.creatGroup.track(with: nil) + BBLogManager.analytics(logType: BBEventAnalyticsLog.clickFamilyButton(entry: .createFamilyGroup)) + }) .throttle(RxConst.milliseconds300Interval, scheduler: MainScheduler.instance) .withUnretained(self) .bind(onNext: { $0.0.newGroupAlertController()}) .disposed(by: disposeBag) joinFamilyButton.rx.tap + .do { _ in BBLogManager.analytics(logType: BBEventAnalyticsLog.clickFamilyButton(entry: .inviteFamily)) } .map { Reactor.Action.joinFamily } .bind(to: reactor.action) .disposed(by: disposeBag) diff --git a/14th-team5-iOS/App/Sources/Presentation/Home/ViewControllers/MainViewController.swift b/14th-team5-iOS/App/Sources/Presentation/Home/ViewControllers/MainViewController.swift index 7f9fc2b1d..defd104c8 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Home/ViewControllers/MainViewController.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Home/ViewControllers/MainViewController.swift @@ -30,6 +30,7 @@ final class MainViewController: BBNavigationViewController, UIC override func viewDidLoad() { super.viewDidLoad() + BBLogManager.analytics(logType: BBEventAnalyticsLog.viewPage(pageName: .main)) } override func bind(reactor: MainViewReactor) { diff --git a/14th-team5-iOS/App/Sources/Presentation/Management/ViewController/FamilyNameSettingViewController.swift b/14th-team5-iOS/App/Sources/Presentation/Management/ViewController/FamilyNameSettingViewController.swift index 76211340f..0de53ab59 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Management/ViewController/FamilyNameSettingViewController.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Management/ViewController/FamilyNameSettingViewController.swift @@ -24,6 +24,11 @@ final class FamilyNameSettingViewController: BBNavigationViewController { override func viewDidLoad() { super.viewDidLoad() + BBLogManager.analytics(logType: BBEventAnalyticsLog.viewPage(pageName: .postDetail)) self.navigationController?.navigationBar.isHidden = true } diff --git a/14th-team5-iOS/App/Sources/Presentation/Privacy/PrivacyViewController.swift b/14th-team5-iOS/App/Sources/Presentation/Privacy/PrivacyViewController.swift index 0fc776c1c..4223e96fc 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Privacy/PrivacyViewController.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Privacy/PrivacyViewController.swift @@ -44,6 +44,7 @@ public final class PrivacyViewController: BaseViewController //MARK: Configure public override func setupUI() { super.setupUI() + BBLogManager.analytics(logType: BBEventAnalyticsLog.viewPage(pageName: .setting)) view.addSubviews(inquiryBannerView, privacyTableView, privacyIndicatorView) } @@ -222,6 +223,7 @@ extension PrivacyViewController { let confirmAction = UIAlertAction(title: "확인", style: .default) { [weak self]_ in guard let self else { return } + BBLogManager.analytics(logType: BBEventAnalyticsLog.clickAccountButton(entry: .logout)) self.reactor?.action.onNext(.didTapLogoutButton) } @@ -242,6 +244,7 @@ extension PrivacyViewController { let confirmAction = UIAlertAction(title: "확인", style: .default) { [weak self ]_ in guard let self else { return } self.reactor?.action.onNext(.didTapFamilyUserResign) + BBLogManager.analytics(logType: BBEventAnalyticsLog.clickAccountButton(entry: .familyResign)) } [cancelAction, confirmAction].forEach(resignAlertController.addAction(_:)) diff --git a/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileFeedPageViewController.swift b/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileFeedPageViewController.swift index 0a77b5599..2beeba523 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileFeedPageViewController.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileFeedPageViewController.swift @@ -84,13 +84,19 @@ extension ProfileFeedPageViewController: ReactorKit.View { extension ProfileFeedPageViewController: UIPageViewControllerDelegate, UIPageViewControllerDataSource { func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { guard let index = feedViewControllers.firstIndex(of: viewController), - index - 1 >= 0 else { return nil } + index - 1 >= 0 else { + BBLogManager.sendError(error: BBCrashError.indexOutBounds) + return nil + } return feedViewControllers[index - 1] } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { guard let index = feedViewControllers.firstIndex(of: viewController), - index + 1 != feedViewControllers.count else { return nil } + index + 1 != feedViewControllers.count else { + BBLogManager.sendError(error: BBCrashError.indexOutBounds) + return nil + } return feedViewControllers[index + 1] } @@ -99,7 +105,10 @@ extension ProfileFeedPageViewController: UIPageViewControllerDelegate, UIPageVie func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) { guard let currentViewController = pageViewController.viewControllers?.first, - let currentIndex = feedViewControllers.firstIndex(of: currentViewController) else { return } + let currentIndex = feedViewControllers.firstIndex(of: currentViewController) else { + BBLogManager.sendError(error: BBCrashError.indexOutBounds) + return + } reactor?.action.onNext(.updatePageViewController(currentIndex)) } diff --git a/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileViewController.swift b/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileViewController.swift index d7e1bb4f4..92607f82c 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileViewController.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileViewController.swift @@ -50,6 +50,7 @@ public final class ProfileViewController: BaseViewController public override func viewDidLoad() { super.viewDidLoad() + BBLogManager.analytics(logType: BBEventAnalyticsLog.viewPage(pageName: .profile)) } public override func setupUI() { @@ -131,6 +132,7 @@ public final class ProfileViewController: BaseViewController profileView.circleButton .rx.tap + .do { _ in BBLogManager.analytics(logType: BBEventAnalyticsLog.clickAccountButton(entry: .profileImageEdit))} .throttle(.milliseconds(300), scheduler: MainScheduler.instance) .withUnretained(self) .bind(onNext: {$0.0.createAlertController()}) @@ -173,6 +175,7 @@ public final class ProfileViewController: BaseViewController .rx.tap .withLatestFrom(reactor.state.compactMap { $0.profileMemberEntity?.memberId }) .throttle(.milliseconds(300), scheduler: MainScheduler.instance) + .do { _ in BBLogManager.analytics(logType: BBEventAnalyticsLog.clickAccountButton(entry: .profileNickNameEdit))} .map { Reactor.Action.didTappedProfileEditButton($0)} .bind(to: reactor.action) .disposed(by: disposeBag) diff --git a/14th-team5-iOS/App/Sources/Presentation/Resign/AccountResignViewController.swift b/14th-team5-iOS/App/Sources/Presentation/Resign/AccountResignViewController.swift index 3adcd6ab3..c280927b6 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Resign/AccountResignViewController.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Resign/AccountResignViewController.swift @@ -26,6 +26,7 @@ final class AccountResignViewController: BaseViewController String { + var result = "" + var previousStringWasCapitalized = false + var previousStringWasNumber = false + + for (index, string) in self.enumerated() { + var mutableString = String(string) + + if !mutableString.isAlphabet { + if index != 0, + !previousStringWasNumber { + mutableString = "_" + mutableString + } + previousStringWasNumber = true + } else if mutableString == mutableString.uppercased() { + mutableString = mutableString.lowercased() + + if index != 0, + !previousStringWasCapitalized { + mutableString = "_" + mutableString + } + previousStringWasCapitalized = true + } else { + previousStringWasCapitalized = false + previousStringWasNumber = false + } + result += mutableString + } + return result + } + + public var isAlphabet: Bool { + let alphabetSet = CharacterSet.uppercaseLetters.union(.lowercaseLetters).union(.whitespacesAndNewlines) + return self.rangeOfCharacter(from: alphabetSet.inverted) == nil + } + public func toDate(with format: String = "yyyy-MM-dd") -> Date { let dateFormatter = DateFormatter.withFormat(format) guard let date = dateFormatter.date(from: self) else { return .now } diff --git a/14th-team5-iOS/Core/Sources/Utils/Logger/BBAnalyticsLogParametable.swift b/14th-team5-iOS/Core/Sources/Utils/Logger/BBAnalyticsLogParametable.swift new file mode 100644 index 000000000..05fb56c91 --- /dev/null +++ b/14th-team5-iOS/Core/Sources/Utils/Logger/BBAnalyticsLogParametable.swift @@ -0,0 +1,16 @@ +// +// BBAnalyticsLogParametable.swift +// Core +// +// Created by 김도현 on 12/19/24. +// + +import Foundation + +public protocol BBAnalyticsLogParametable: RawRepresentable, CustomStringConvertible where RawValue == String { } + +public extension BBAnalyticsLogParametable { + var description: String { + self.rawValue + } +} diff --git a/14th-team5-iOS/Core/Sources/Utils/Logger/BBAnalyticsLogType.swift b/14th-team5-iOS/Core/Sources/Utils/Logger/BBAnalyticsLogType.swift new file mode 100644 index 000000000..2983502e9 --- /dev/null +++ b/14th-team5-iOS/Core/Sources/Utils/Logger/BBAnalyticsLogType.swift @@ -0,0 +1,38 @@ +// +// BBAnalyticsLogType.swift +// Core +// +// Created by 김도현 on 12/19/24. +// + +import Foundation + +public protocol BBAnalyticsLogType { + var name: String { get } + var params: [String: Any] { get } +} + +public extension BBAnalyticsLogType { + var name: String { + Mirror(reflecting: self) + .children + .first? + .label? + .toSnakeCase() ?? String(describing: self).toSnakeCase() + } + + var params: [String: Any] { + var dict: [String: Any] = [:] + + let enumMirror = Mirror(reflecting: self) + + guard let associated = enumMirror.children.first else { return dict } + + for enumParams in Mirror(reflecting: associated.value).children { + guard let label = enumParams.label?.toSnakeCase() else { continue } + dict[label] = enumParams.value + } + + return dict + } +} diff --git a/14th-team5-iOS/Core/Sources/Utils/Logger/BBEventAnalyticsLog.swift b/14th-team5-iOS/Core/Sources/Utils/Logger/BBEventAnalyticsLog.swift new file mode 100644 index 000000000..7462c5953 --- /dev/null +++ b/14th-team5-iOS/Core/Sources/Utils/Logger/BBEventAnalyticsLog.swift @@ -0,0 +1,66 @@ +// +// BBEventAnalyticsLog.swift +// Core +// +// Created by 김도현 on 12/19/24. +// + +import Foundation + +public enum BBEventAnalyticsLog: BBAnalyticsLogType { + case viewPage(pageName: PageName) + case clickAccountButton(entry: AccountButtonEntry) + case clickFamilyButton(entry: FamilyButtonEntry) + case clickCameraButton(entry: CameraButtonEntry) +} + + +public extension BBEventAnalyticsLog { + enum PageName: String, BBAnalyticsLogParametable { + case main + case calendar = "calendar" + case camera = "camera" + case cameraDetail = "camera_detail" + case familyManagement = "family_management" + case familyGroupNameSetting = "family_group_name_setting" + case postDetail = "post_detail" + case profile + case setting + case resign + + public var description: String { + self.rawValue + } + } + + enum AccountButtonEntry: String, BBAnalyticsLogParametable { + case profileImageEdit = "profile_image_edit" + case profileNickNameEdit = "profile_nickname_edit" + case logout + case familyResign = "family_resign" + case resign + + + public var description: String { + self.rawValue + } + } + + enum FamilyButtonEntry: String, BBAnalyticsLogParametable { + case createFamilyGroup = "create_family_group" + case familyNameSetting = "family_name_setting" + case inviteFamily = "invite_family" + + + public var description: String { + self.rawValue + } + } + + enum CameraButtonEntry: String, BBAnalyticsLogParametable { + case shutter + case failedAlertConfirm = "failed_alert_confirm" + case failedAlertCancle = "failed_alert_cancle" + } + +} diff --git a/14th-team5-iOS/Core/Sources/Utils/Logger/BBLogManager.swift b/14th-team5-iOS/Core/Sources/Utils/Logger/BBLogManager.swift new file mode 100644 index 000000000..7ee49ae13 --- /dev/null +++ b/14th-team5-iOS/Core/Sources/Utils/Logger/BBLogManager.swift @@ -0,0 +1,69 @@ +// +// BBLogManager.swift +// Core +// +// Created by 김도현 on 12/12/24. +// + +import FirebaseCrashlytics +import FirebaseAnalytics + + +public enum BBLogManager { + + public static func setMemberId( + memberId: String, + function: String = #function, + fileName: String = #file + ) { + Crashlytics.crashlytics().setUserID(memberId) + Analytics.setUserID(memberId) + + BBLogger.logDebug( + function: function, + fileName: fileName, + category: "Analytics", + message: "Firebase 멤버 ID 설정" + ) + } + + public static func analytics( + logType: any BBAnalyticsLogType + ) { + Analytics.logEvent(logType.name, parameters: logType.params) + } + + public static func sendError( + message: String, + function: String = #function, + fileName: String = #file + ) { + Crashlytics.crashlytics().log(message) + + BBLogger.logError( + function: function, + fileName: fileName, + category: "Analytics Error", + message: message + ) + } + + public static func sendError( + error: any Error, + function: String = #function, + fileName: String = #file + ) { + Crashlytics.crashlytics().setCrashlyticsCollectionEnabled(true) + Crashlytics.crashlytics().record(error: error) + + BBLogger.logError( + function: function, + fileName: fileName, + category: "Analytics Error", + message: error.localizedDescription + ) + + } + +} + diff --git a/14th-team5-iOS/Data/Sources/Storages/UserDefaults/FamilyUserDefaults/FamilyUserDefaults.swift b/14th-team5-iOS/Data/Sources/Storages/UserDefaults/FamilyUserDefaults/FamilyUserDefaults.swift index f64c845fc..2e46e00f4 100644 --- a/14th-team5-iOS/Data/Sources/Storages/UserDefaults/FamilyUserDefaults/FamilyUserDefaults.swift +++ b/14th-team5-iOS/Data/Sources/Storages/UserDefaults/FamilyUserDefaults/FamilyUserDefaults.swift @@ -88,6 +88,7 @@ final public class FamilyInfoUserDefaults: FamilyInfoUserDefaultsType { public func loadFamilyId() -> String? { guard let familyId: String = userDefaults[.familyId] else { + BBLogManager.sendError(message: "not Found FamilyID") return nil } return familyId diff --git a/14th-team5-iOS/Data/Sources/Trash/Account/AccountRepository/AccountRepository.swift b/14th-team5-iOS/Data/Sources/Trash/Account/AccountRepository/AccountRepository.swift index 37a8bed5f..ff27e1a52 100644 --- a/14th-team5-iOS/Data/Sources/Trash/Account/AccountRepository/AccountRepository.swift +++ b/14th-team5-iOS/Data/Sources/Trash/Account/AccountRepository/AccountRepository.swift @@ -123,7 +123,7 @@ public final class AccountRepository: AccountImpl { App.Repository.member.memberID.accept(memberInfo.memberId) App.Repository.member.familyId.accept(memberInfo.familyId) App.Repository.member.nickname.accept(memberInfo.name) - + BBLogManager.setMemberId(memberId: memberInfo.memberId) let member: FamilyMemberProfileEntity = FamilyMemberProfileEntity(memberId: memberInfo.memberId, profileImageURL: memberInfo.imageUrl, name: memberInfo.name) } diff --git a/Tuist/ProjectDescriptionHelpers/ConfigurationName+Templates.swift b/Tuist/ProjectDescriptionHelpers/ConfigurationName+Templates.swift index 1ce903a32..8912029a5 100644 --- a/Tuist/ProjectDescriptionHelpers/ConfigurationName+Templates.swift +++ b/Tuist/ProjectDescriptionHelpers/ConfigurationName+Templates.swift @@ -26,16 +26,19 @@ extension Configuration { case .dev: return .debug( name: BuildTarget.dev.configurationName, + settings: ["DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym"], xcconfig: .relativeToXCConfig(type: .dev) ) case .stg: return .release( name: BuildTarget.stg.configurationName, + settings: ["DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym"], xcconfig: .relativeToXCConfig(type: .stg) ) case .prd: return .release( name: BuildTarget.prd.configurationName, + settings: ["DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym"], xcconfig: .relativeToXCConfig(type: .prd) ) } diff --git a/Tuist/ProjectDescriptionHelpers/Modular+Templates.swift b/Tuist/ProjectDescriptionHelpers/Modular+Templates.swift index ef25909d5..3485ca015 100644 --- a/Tuist/ProjectDescriptionHelpers/Modular+Templates.swift +++ b/Tuist/ProjectDescriptionHelpers/Modular+Templates.swift @@ -19,7 +19,12 @@ public struct ModularFactory { var infoPlist: InfoPlist? var sources: SourceFilesList? var resources: ResourceFileElements? - var settings: Settings? + var settings: Settings? = .settings( + base: [ + "DEBUG_INFORMATION_FORMAT": "dwarf-with-dsym", + "OTHER_LDFLAGS": "$(inherited) -ObjC" + ] + ) var entitlements: Entitlements? @@ -87,6 +92,7 @@ extension Target { sources: factory.sources, resources: factory.resources, entitlements: factory.entitlements, + scripts: [.firebaseInfoByConfiguration, .firebaseCrashlytics], dependencies: factory.dependencies, settings: factory.settings ) @@ -109,7 +115,7 @@ extension Target { return .target( name: layer.rawValue, destinations: .iOS, - product: factory.products.isFramework ? .staticFramework : .framework, + product: .staticFramework, bundleId: "com.\(layer.rawValue).project".lowercased(), deploymentTargets: factory.deploymentTargets, infoPlist: factory.infoPlist, @@ -123,7 +129,7 @@ extension Target { return .target( name: layer.rawValue, destinations: .iOS, - product: factory.products.isLibrary ? .framework : .staticFramework, + product: .staticFramework, bundleId: "com.\(layer.rawValue).project".lowercased(), deploymentTargets: factory.deploymentTargets, infoPlist: factory.infoPlist, diff --git a/Tuist/ProjectDescriptionHelpers/ModuleType+Templates.swift b/Tuist/ProjectDescriptionHelpers/ModuleType+Templates.swift index b2cbfc759..f0eb1198c 100644 --- a/Tuist/ProjectDescriptionHelpers/ModuleType+Templates.swift +++ b/Tuist/ProjectDescriptionHelpers/ModuleType+Templates.swift @@ -41,7 +41,6 @@ public enum ModuleLayer: String, CaseIterable, ModuleType { case .App: return [ .target(name: "WidgetExtension"), - .external(name: "FirebaseAnalytics"), .external(name: "FirebaseMessaging"), .external(name: "Mixpanel"), .external(name: "RxDataSources"), @@ -68,6 +67,8 @@ public enum ModuleLayer: String, CaseIterable, ModuleType { case .Core: return [ .with(.DesignSystem), + .external(name: "FirebaseAnalytics", condition: .when(.all)), + .external(name: "FirebaseCrashlytics", condition: .when(.all)), .external(name: "SnapKit", condition: .when(.all)), .external(name: "Then", condition: .when(.all)), .external(name: "Kingfisher", condition: .when(.all)), diff --git a/Tuist/ProjectDescriptionHelpers/Project+Templates.swift b/Tuist/ProjectDescriptionHelpers/Project+Templates.swift index 98094bae9..ebeb7e1e9 100644 --- a/Tuist/ProjectDescriptionHelpers/Project+Templates.swift +++ b/Tuist/ProjectDescriptionHelpers/Project+Templates.swift @@ -58,7 +58,7 @@ extension Project { name: name, settings: .settings( base: [ - "OTHER_LDFLAGS": ["-ObjC"], + "OTHER_LDFLAGS": "$(inherited) -ObjC", "MARKETING_VERSION": "1.2.4", "CURRENT_PROJECT_VERSION": "1", "VERSIONING_SYSTEM": "apple-generic" diff --git a/Tuist/ProjectDescriptionHelpers/TargetScript+Templates.swift b/Tuist/ProjectDescriptionHelpers/TargetScript+Templates.swift new file mode 100644 index 000000000..0971d746a --- /dev/null +++ b/Tuist/ProjectDescriptionHelpers/TargetScript+Templates.swift @@ -0,0 +1,41 @@ +// +// TargetScript+Templates.swift +// ProjectDescriptionHelpers +// +// Created by 김도현 on 12/12/24. +// + +import ProjectDescription +import Foundation + + +public extension TargetScript { + static let firebaseCrashlytics = TargetScript.post( + script: """ + case "${CONFIGURATION}" in + "PRD" | "Release" ) + BASE_PATH=$(realpath "${SRCROOT}/../..") + "${BASE_PATH}/Tuist/.build/checkouts/firebase-ios-sdk/Crashlytics/run" -gsp "${BASE_PATH}/14th-team5-iOS/App/Resources/GoogleService-Info.plist" -p ios "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}" + esac + """, + name: "Firebase Crashlytics", + inputPaths: [ + "${DWARF_DSYM_FOLDER_PATH}/${DWARF_DSYM_FILE_NAME}/Contents/Resources/DWARF/${TARGET_NAME}", + "$(SRCROOT)/$(BUILT_PRODUCTS_DIR)/$(INFOPLIST_PATH)" + ], + basedOnDependencyAnalysis: false + ) + + static let firebaseInfoByConfiguration = TargetScript.post( + script: """ + case "${CONFIGURATION}" in + "PRD" ) + cp -r "$SRCROOT/Resources/GoogleService-Info.plist" "${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app/GoogleService-Info.plist" + ;; + *) + esac + """, + name: "Firebase Info copy by Configuration", + basedOnDependencyAnalysis: false + ) +} From cef185f355482d90b67085e5309cc481622caf0f Mon Sep 17 00:00:00 2001 From: Do-hyun-Kim Date: Thu, 19 Dec 2024 21:36:53 +0900 Subject: [PATCH 2/3] =?UTF-8?q?feat:=20github=20Action=20PRD=20Lane=20dsym?= =?UTF-8?q?=20Upload=20Method=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- fastlane/Fastfile | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/fastlane/Fastfile b/fastlane/Fastfile index 48f224b90..f64b4173f 100644 --- a/fastlane/Fastfile +++ b/fastlane/Fastfile @@ -156,6 +156,11 @@ platform :ios do new_build_number = build_num + 1 + version = get_version_number( + xcodeproj: "14th-team5-iOS/App/App.xcodeproj", + target: "#{PRD_SCHEME}" + ) + increment_build_number( xcodeproj: "14th-team5-iOS/App/App.xcodeproj", @@ -186,6 +191,17 @@ platform :ios do } ) + download_dsyms( + app_identifier: "com.5ing.bibbi", + version: version, + build_number: new_build_number, + output_directory: "./14th-team5-iOS" + ) + + upload_symbols_to_crashlytics( + gsp_path: "14th-team5-iOS/App/Resources/GoogleService-Info.plist" + ) + upload_to_testflight(skip_waiting_for_build_processing: true) From 160789ebf57abe1ca2c40ea6d8ebe435ed4af005 Mon Sep 17 00:00:00 2001 From: Do-hyun-Kim Date: Fri, 20 Dec 2024 15:47:39 +0900 Subject: [PATCH 3/3] =?UTF-8?q?fix:=20ViewController=20Analytics=20LogEven?= =?UTF-8?q?t=20Method=20Reactor=EB=A1=9C=20=EC=BD=94=EB=93=9C=20=EC=9D=B4?= =?UTF-8?q?=EC=A0=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Sources/Application/Navigator/CameraDisplayNavigator.swift | 2 -- .../App/Sources/Application/Navigator/CameraNavigator.swift | 1 - .../Management/Reactor/FamilyNameSettingViewReactor.swift | 2 +- .../ViewController/FamilyNameSettingViewController.swift | 1 - .../Sources/Presentation/Privacy/PrivacyViewController.swift | 1 - .../Presentation/Privacy/Reactor/PrivacyViewReactor.swift | 1 + .../Sources/Presentation/Profile/ProfileViewController.swift | 1 - .../Presentation/Profile/Reactor/ProfileViewReactor.swift | 1 + .../Core/Sources/Utils/Logger/BBEventAnalyticsLog.swift | 2 -- 9 files changed, 3 insertions(+), 9 deletions(-) diff --git a/14th-team5-iOS/App/Sources/Application/Navigator/CameraDisplayNavigator.swift b/14th-team5-iOS/App/Sources/Application/Navigator/CameraDisplayNavigator.swift index 77e557d63..32cebdeea 100644 --- a/14th-team5-iOS/App/Sources/Application/Navigator/CameraDisplayNavigator.swift +++ b/14th-team5-iOS/App/Sources/Application/Navigator/CameraDisplayNavigator.swift @@ -29,11 +29,9 @@ final class CameraDisplayNavigator: CameraDisplayNavigatorProtocol { func showErrorAlert() { let confirmHandler: BBAlertActionHandler = { [weak self] alert in self?.toCamera() - BBLogManager.analytics(logType: BBEventAnalyticsLog.clickCameraButton(entry: .failedAlertConfirm)) alert?.close() } let cancelHandler: BBAlertActionHandler = { [weak self] alert in - BBLogManager.analytics(logType: BBEventAnalyticsLog.clickCameraButton(entry: .failedAlertCancle)) self?.toHome() alert?.close() } diff --git a/14th-team5-iOS/App/Sources/Application/Navigator/CameraNavigator.swift b/14th-team5-iOS/App/Sources/Application/Navigator/CameraNavigator.swift index 7dc46f7ab..da34040b7 100644 --- a/14th-team5-iOS/App/Sources/Application/Navigator/CameraNavigator.swift +++ b/14th-team5-iOS/App/Sources/Application/Navigator/CameraNavigator.swift @@ -31,7 +31,6 @@ final class CameraNavigator: CameraNavigatorProtocol { func showErrorAlert(_ type: UploadLocation) { let confirmHandler: BBAlertActionHandler = makeConfirmHandler(for: type) let cancelHandler: BBAlertActionHandler = { [weak self] alert in - BBLogManager.analytics(logType: BBEventAnalyticsLog.clickCameraButton(entry: .failedAlertCancle)) self?.toHome() alert?.close() } diff --git a/14th-team5-iOS/App/Sources/Presentation/Management/Reactor/FamilyNameSettingViewReactor.swift b/14th-team5-iOS/App/Sources/Presentation/Management/Reactor/FamilyNameSettingViewReactor.swift index 21191a200..67a250d72 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Management/Reactor/FamilyNameSettingViewReactor.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Management/Reactor/FamilyNameSettingViewReactor.swift @@ -100,7 +100,7 @@ public final class FamilyNameSettingViewReactor: Reactor { case let .didTapUpdateFamilyGroupNickname(type): let familyName = type == .initial ? nil : currentState.familyGroupNickName let updateFamilyBody = UpdateFamilyNameRequest(familyName: familyName) - + BBLogManager.analytics(logType: BBEventAnalyticsLog.clickFamilyButton(entry: .familyNameSetting)) return updateFamilyNameUseCase.execute(body: updateFamilyBody) .asObservable() .compactMap { $0 } diff --git a/14th-team5-iOS/App/Sources/Presentation/Management/ViewController/FamilyNameSettingViewController.swift b/14th-team5-iOS/App/Sources/Presentation/Management/ViewController/FamilyNameSettingViewController.swift index 0de53ab59..709723769 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Management/ViewController/FamilyNameSettingViewController.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Management/ViewController/FamilyNameSettingViewController.swift @@ -152,7 +152,6 @@ final class FamilyNameSettingViewController: BBNavigationViewController //MARK: Configure public override func setupUI() { super.setupUI() - BBLogManager.analytics(logType: BBEventAnalyticsLog.viewPage(pageName: .setting)) view.addSubviews(inquiryBannerView, privacyTableView, privacyIndicatorView) } diff --git a/14th-team5-iOS/App/Sources/Presentation/Privacy/Reactor/PrivacyViewReactor.swift b/14th-team5-iOS/App/Sources/Presentation/Privacy/Reactor/PrivacyViewReactor.swift index b49e66237..a9cb2741c 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Privacy/Reactor/PrivacyViewReactor.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Privacy/Reactor/PrivacyViewReactor.swift @@ -64,6 +64,7 @@ public final class PrivacyViewReactor: Reactor { public func mutate(action: Action) -> Observable { switch action { case .viewDidLoad: + BBLogManager.analytics(logType: BBEventAnalyticsLog.viewPage(pageName: .setting)) return .concat( .just(.setLoading(true)), .merge( diff --git a/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileViewController.swift b/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileViewController.swift index fb6a959a0..103f03c6f 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileViewController.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Profile/ProfileViewController.swift @@ -175,7 +175,6 @@ public final class ProfileViewController: BaseViewController .rx.tap .withLatestFrom(reactor.state.compactMap { $0.profileMemberEntity?.memberId }) .throttle(.milliseconds(300), scheduler: MainScheduler.instance) - .do { _ in BBLogManager.analytics(logType: BBEventAnalyticsLog.clickAccountButton(entry: .profileNickNameEdit))} .map { Reactor.Action.didTappedProfileEditButton($0)} .bind(to: reactor.action) .disposed(by: disposeBag) diff --git a/14th-team5-iOS/App/Sources/Presentation/Profile/Reactor/ProfileViewReactor.swift b/14th-team5-iOS/App/Sources/Presentation/Profile/Reactor/ProfileViewReactor.swift index c93bb600f..bee7eebe7 100644 --- a/14th-team5-iOS/App/Sources/Presentation/Profile/Reactor/ProfileViewReactor.swift +++ b/14th-team5-iOS/App/Sources/Presentation/Profile/Reactor/ProfileViewReactor.swift @@ -151,6 +151,7 @@ public final class ProfileViewReactor: Reactor { profileNavigator.toPrivacy(memberId) return .empty() case let .didTappedProfileEditButton(memberId): + BBLogManager.analytics(logType: BBEventAnalyticsLog.clickAccountButton(entry: .profileNickNameEdit)) profileNavigator.toAccountNickname(memberId) return .empty() case let .didTappedAlertButton(memberId): diff --git a/14th-team5-iOS/Core/Sources/Utils/Logger/BBEventAnalyticsLog.swift b/14th-team5-iOS/Core/Sources/Utils/Logger/BBEventAnalyticsLog.swift index 7462c5953..a50023cf1 100644 --- a/14th-team5-iOS/Core/Sources/Utils/Logger/BBEventAnalyticsLog.swift +++ b/14th-team5-iOS/Core/Sources/Utils/Logger/BBEventAnalyticsLog.swift @@ -59,8 +59,6 @@ public extension BBEventAnalyticsLog { enum CameraButtonEntry: String, BBAnalyticsLogParametable { case shutter - case failedAlertConfirm = "failed_alert_confirm" - case failedAlertCancle = "failed_alert_cancle" } }