我构建了一个 ErrorLogger,如下所示,以确保所有错误消息和用户错误都将被统一记录。然而,在调用 ErrorLogger 时初始化 struts 此时非常冗长。
我想让它尽可能简单。
正如您在下面的示例中看到的,在我初始化 ErrorLocation 的调用中,我必须输入
ErrorLocation(文件路径:#file,行:#line,列:#column,funcName:#function)
我希望能够节省一些输入,而不必在我的 Service 类
中一遍又一遍地重新输入,每当我想记录错误时。
有更好的方法吗?我愿意接受建议。
使用ErrorLogger
func saveUserProfile(uid: String, user: Dictionary<String, String>,completion: @escaping (Result<String>) -> Void) {
// Save user profile data to the Firebase database - A User is born.
firebaseDatabase.child(kUSER).child(uid).updateChildValues(user, withCompletionBlock: { (error: Error?, ref: DatabaseReference) in
if error != nil {
// Uh-oh, an error occurred!
let logError = LogError(errorCode: kSAVING_USER_PROFILE_ERROR_CODE, errorLocation: ErrorLocation(filePath: #file, line: #line, column: #column, funcName: #function), description: "An error occurred while writing the user profile data to the firebase database", errorMessage: "\(error.debugDescription)")
let userError = UserError(errorMessage: kSAVING_USER_PROFILE_ERROR_MESSAGE)
return completion(.Error(errorCode: kSAVING_USER_PROFILE_ERROR_CODE, logError: logError, userError: userError))
} else {
// The user has been written to the database - A User has been born.
return completion(.Success("The user was successfully written to the database"))
}
})
}
*控制台输出*
2018-03-10 18:35:30 PM ::Error::errorCode:: 4021 ::class::UserFBService.swift
::functionName::fetchCurrentUserProfile(completion:) ::lineNumber::69
::columnName162 ::UserID::ZE2837447f9tQ0i1z1AHHAFFFWACbg2 ::description::
An error occurred while fetching the current user's profile, some of the
user's profile data was missing from Firebase ::errorMessage::
ErrorLogger.swift
enum Result<T> {
case Success(T)
case Incomplete(T, errorCode: Int, logError: LogError, userError: UserError)
case Error(errorCode: Int, logError: LogError?, userError: UserError?)
}
struct LogError {
var timestamp: String
var header: String
var errorCode: Int
var errorLocation: ErrorLocation
var userID: String
var description: String //describes the type of error
var errorMessage: String //actual error returned by given function
init(timestamp: String = "", header: String = "", errorCode: Int, errorLocation: ErrorLocation, userID: String = "", description: String, errorMessage: String) {
self.timestamp = timestamp
self.header = header
self.errorCode = errorCode
self.errorLocation = errorLocation
self.userID = userID
self.description = " ::description::" + description
self.errorMessage = " ::errorMessage::" + errorMessage
if timestamp.isEmpty {
self.timestamp = Date().currentUTCTimestamp
}
if header.isEmpty {
self.header = " ::Error::errorCode::"
}
if userID.isEmpty {
self.userID = getUserID()
}
}
func getUserID() -> String {
var userUID: String = ""
if Auth.auth().currentUser != nil {
userUID = (Auth.auth().currentUser!.uid.isEmpty ? "" : Auth.auth().currentUser!.uid)
} else {
userUID = ""
}
let userUIDStr: String = " ::UserID::" + userUID
return userUIDStr
}
func toString() -> String {
let fullErrorMessageStr: String = "\(timestamp) \(header) \(errorCode) \(errorLocation.toString()) \(userID) \(description) \(errorMessage)"
return fullErrorMessageStr
}
}
struct ErrorLocation {
var filePath: String
var line: Int
var column: Int
var funcName: String
init(filePath: String, line: Int, column: Int, funcName: String) {
self.filePath = filePath
self.line = line
self.column = column
self.funcName = funcName
}
func getClassNameFromFilePath() -> String{
var className: String = ""
if !filePath.isEmpty {
let components = filePath.components(separatedBy: "/")
className = components.isEmpty ? "" : components.last!
}
return className
}
func toString() -> String {
let errorLocationStr: String = "::class::\(getClassNameFromFilePath()) ::functionName::\(funcName) ::lineNumber::\(line) ::columnName\(column)"
return errorLocationStr
}
}
struct UserError {
var errorTitle: String
var errorMessage: String
init(errorTitle: String, errorMessage: String) { //use this function overloading to specify
//a different error title when necessary
self.errorTitle = errorTitle
self.errorMessage = errorMessage
}
init(errorMessage: String) {
self.errorTitle = kOOPS_USER_ERROR_TITLE //error title defaults to "Oops!" for most cases
self.errorMessage = errorMessage
}
}
extension Date {
var currentUTCTimestamp: String {
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "UTC")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss a"
//formatter.dateFormat = "MMM dd, yyyy hh:mm a"
return formatter.string(from: self)
}
}
最佳答案
您可以使用默认参数值:
struct ErrorLocation {
init(filePath: String = #file, line: Int = #line, column: Int = #column, funcName: String = #function) {
并调用不带参数的初始化程序:ErrorLocation()
。编译器将从调用站点推断这些参数的值。
请注意,如果 ErrorLocation
实例化发生在调用层次结构的下方,您还需要转发这些参数,这意味着每个函数都应该具有这些参数和这些值,直到您脱离了记录器层次结构。
所以而不是
struct LogError {
init(timestamp: String = "", header: String = "", errorCode: Int, errorLocation: ErrorLocation, userID: String = "", description: String, errorMessage: String) {
,你需要这样的东西
struct LogError {
init(timestamp: String = "", header: String = "", errorCode: Int, userID: String = "", description: String, errorMessage: String, filePath: String = #file, line: Int = #line, column: Int = #column, funcName: String = #function) {
let errorLocation = ErrorLocation(filePath: filePath, line: lone, column: column, funcName: funcName)
// rest of the initializer
关于ios - 如何在 Swift 中将 #file、#line、#column、#funcion 传递给我的 ErrorLogger,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/49212605/