Reputation: 207
I have this struct
defined to be used in my ErrorLogger
. However, some of the parameters such as Timestamp I'd like to get right away with the functions listed. How can I pass a default value instead of nil for the parameters: header
, errorLocation
, userId
? In order to signal that a default value will be used if no other value is provided.
The idea is that if I pass some default value to these parameters then the struct functions would be called to get the values or else the values would be overwritten by whatever the user passes during initialization.
I am also getting the error:
self used before all stored properties are initialized
on this line:
self.errorLocation = getErrorLocation()
Initializing struct from viewController:
let logError = LogError(header: nil, errorLocation: nil, userID: nil, description: "An error occurred while verifying if the user profile exists", errorMessage: "\(error?.localizedDescription ?? "")")
struct in ErrorLogger:
struct LogError {
var header: String
var errorLocation: String
var userID: String
var description: String //describes the type of error
var errorMessage: String //actual error returned by given function
//TODO: add timestamp to lofError
//TODO: add logEvent (enum: Error, Info) For example: data validation errors can be of event Info
init(header: String?, errorLocation: String?, userID: String?, description: String, errorMessage: String) {
if header != nil {
self.header = header!
} else {
self.header = " ::Error::"
}
if errorLocation != nil {
self.errorLocation = errorLocation!
} else {
self.errorLocation = getErrorLocation()
}
if userID != nil {
self.userID = userID!
} else {
self.userID = getUserID()
}
self.description = " ::description::" + description
self.errorMessage = " ::errorMessage::" + errorMessage
}
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 getErrorLocation() -> String {
// Get class name
let filePath: String = #file
let components = filePath.components(separatedBy: "/")
let className: String = components.isEmpty ? "" : components.last!
// Get line number
let line: Int = #line
// Get column number
let column: Int = #column
// Get function name
let funcName: String = #function
let errorLocationStr: String = " ::className::\(className)::lineNumber\(line)::columnNumber\(column)::funcName::\(funcName)"
return errorLocationStr
}
func toString() -> String {
let completeLogErrorMessageStr: String = header + errorLocation + userID + description + errorMessage
return completeLogErrorMessageStr
}
}
Upvotes: 1
Views: 7027
Reputation: 318774
You have to give all of the properties a valid before you can call methods. I would refactor your init
to something like this:
init(header: String?, errorLocation: String?, userID: String?, description: String, errorMessage: String) {
self.header = header ?? " ::Error::"
self.errorLocation = errorLocation ?? ""
self.userID = userID ?? ""
self.description = " ::description::" + description
self.errorMessage = " ::errorMessage::" + errorMessage
if errorLocation == nil {
self.errorLocation = getErrorLocation()
}
if userID == nil {
self.userID = getUserID()
}
}
That will fix the "self used before all stored properties are initialized" error.
To use default values, update the signature:
init(header: String? = nil, errorLocation: String? = nil, userID: String? = nil, description: String, errorMessage: String) {
// nothing else changes
}
Now you can call the initializer without the nil
parameters.
For example:
let logError = LogError(header: nil, errorLocation: nil, userID: nil, description: "An error occurred while verifying if the user profile exists", errorMessage: "\(error?.localizedDescription ?? "")")
becomes:
let logError = LogError(description: "An error occurred while verifying if the user profile exists", errorMessage: "\(error?.localizedDescription ?? "")")
Upvotes: 2