iOS Swift: отправка информации журнала в приложение iOS из платформы iOS - PullRequest
1 голос
/ 28 октября 2019

Я пытаюсь выяснить, как отправить информацию о регистрации из моей платформы iOS в мое приложение iOS. Внутри моего приложения для iOS у меня есть настройка Crashlytics, и я хотел бы использовать Crashlytics.sharedInstance().recordError(error) всякий раз, когда я получаю некоторые журналы из приложения, а также мою инфраструктуру iOS.

Я прочитал несколько ответов, упомянув, что Crashlytics может бытьинициализируется только один раз в приложении, и не рекомендуется снова инициализировать в рамках. (например, Ссылка 1 ), Ссылка 2 , Ссылка 3 )

У кого-нибудь есть работающее решение для такого требования?

РЕДАКТИРОВАТЬ 1 (добавив больше кода из моей структуры, где мне нужно получить ошибки)

public final class MyAppSession {

    public fileprivate(set) var isValid: Bool = false

    let itemKey = MyAppSession.MyAppKeychainAccount
    let keychainAccessGroupName = MyAppConfigured?.keyChainGroup

    /**
     Attempts to restore a locally stored session.
     */
    public static func savedSession() -> MyAppSession? {

        do {

            let itemKey = MyAppSession.MyAppKeychainAccount
            let keychainAccessGroupName = MyAppConfigured?.keyChainGroup

            let queryLoad: [String: AnyObject] = [
                kSecClass as String: kSecClassGenericPassword,
                kSecAttrAccount as String: itemKey as AnyObject,
                kSecReturnData as String: kCFBooleanTrue,
                kSecMatchLimit as String: kSecMatchLimitOne,
                kSecAttrAccessGroup as String: keychainAccessGroupName as AnyObject
            ]

            var result: AnyObject?

            let resultCodeLoad = withUnsafeMutablePointer(to: &result) {
                SecItemCopyMatching(queryLoad as CFDictionary, UnsafeMutablePointer($0))
            }

            if resultCodeLoad == noErr {
                if let result = result as? Data {
                    if let arrayFromData = NSKeyedUnarchiver.unarchiveObject(with: result) as? NSDictionary {
                        // Found successfully
                        return MyAppSession(accessToken: (arrayFromData["accessToken"] as? String)!, refreshToken: (arrayFromData["refreshToken"] as? String)!)
                    }
                }
            } else {
                MyApp.log("No Keychain elements present.", logLevel: .verbose)
                MyAppLogger.sendLogs(message: "Logger Test. No Keychain elements present.")
            }

            let keychainData = try Locksmith.loadDataForUserAccount(userAccount: MyAppSession.MyAppKeychainAccount)
            if let accessToken = keychainData?[MyAppSession.accessTokenKeychainKey] as? String,
                let refreshToken = keychainData?[MyAppSession.refreshTokenKeychainKey] as? String {

                MyApp.log("Restored saved session.", logLevel: .verbose)

                return MyAppSession(accessToken: accessToken, refreshToken: refreshToken)

            }
            else {
                return nil
            }

        }
        catch {
            return nil
        }

    }

    init?(accessToken: String, refreshToken: String) {

        // Save credentials to the keychain.
        do {

            try Locksmith.updateData(
                data: [MyAppSession.accessTokenKeychainKey: accessToken as AnyObject, MyAppSession.refreshTokenKeychainKey: refreshToken as AnyObject],
                forUserAccount: MyAppSession.MyAppKeychainAccount)

            if let configuration = MyAppConfigured {
                if configuration.keyChainGroup == "" {
                    let valueData = [MyAppSession.accessTokenKeychainKey: accessToken as AnyObject, MyAppSession.refreshTokenKeychainKey: refreshToken as AnyObject]

                    let data = NSKeyedArchiver.archivedData(withRootObject: valueData)

                    let queryAdd: [String: AnyObject] = [
                        kSecClass as String: kSecClassGenericPassword,
                        kSecAttrAccount as String: itemKey as AnyObject,
                        kSecValueData as String: data as AnyObject,
                        kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked
                    ]

                    let resultCode = SecItemAdd(queryAdd as CFDictionary, nil)

                    if resultCode != noErr {
                        MyApp.log("Keychain groupname empty: \(resultCode)", logLevel: .verbose)
                    }
                    else {
                        MyApp.log("KeyChain Saving Success", logLevel: .verbose)
                    }

                }

                else {
                    let valueData = [MyAppSession.accessTokenKeychainKey: accessToken as AnyObject, MyAppSession.refreshTokenKeychainKey: refreshToken as AnyObject]

                    let data = NSKeyedArchiver.archivedData(withRootObject: valueData)

                    let queryAdd: [String: AnyObject] = [
                        kSecClass as String: kSecClassGenericPassword,
                        kSecAttrAccount as String: itemKey as AnyObject,
                        kSecValueData as String: data as AnyObject,
                        kSecAttrAccessible as String: kSecAttrAccessibleWhenUnlocked,
                        kSecAttrAccessGroup as String: keychainAccessGroupName as AnyObject
                    ]

                    let resultCode = SecItemAdd(queryAdd as CFDictionary, nil)

                    if resultCode != noErr {
                        MyApp.log("Error saving to Keychain: \(resultCode)", logLevel: .verbose)
                    }
                    else {
                        MyApp.log("KeyChain Saving Success", logLevel: .verbose)
                    }
                }
            }

            isValid = true

            MyApp.log("Created new session.")

        }
        catch {
            return nil
        }

    }
}

Ответы [ 2 ]

2 голосов
/ 28 октября 2019

Один из вариантов - делегировать запись ошибки в ваше приложение. Это делает его более гибким.

Например:

protocol MyFrameworkErrorHandlingDelegate: AnyObject {
    func didReceiveError(_ error: Error)
}

Тогда в вашем приложении вы можете создать расширение по умолчанию для этого

extension MyFrameworkErrorHandlingDelegate {
     func didReceiveError(_ error: Error) {
         Crashlytics.sharedInstance().recordError(error)
     }
}

Проблема с этимподход заключается в том, чтобы решить, где его использовать или где назначить делегата, и это зависит от того, что делает ваша структура и как ваше приложение использует структуру.

РЕДАКТИРОВАТЬ:

Отказ от ответственности: Это не самый эффективный способ сделать это, но это будет самый прямой.

protocol MyFrameworkErrorHandlingDelegate: AnyObject {
    func didReceiveError(_ error: Error)
}

class MyAppLogger {

    static var delegate: MyFrameworkErrorHandlingDelegate?

    static func log(_ error: Error) {
        delegate?.didReceiveError(error)
    }
}

class AppDelegate: UIApplicationDelegate, MyFrameworkErrorHandlingDelegate

позже в вашем AppDelegate

MyAppLogger.delegate = self
0 голосов
/ 28 октября 2019

просто создайте экземпляр в appdelegate и используйте его в своих фреймворках. Не создавайте Crashlytics в фреймворке, просто используйте их там.

...