We’ve all gotten used to debugging by printing out the data information to the console so that we can easily investigate the problem. If our app involves payment transactions or the information needs to be secure, but we still need to log it for tracking, for statistics of user habits or for bug fixes. In this article, we will hide sensitive information when logging out.
Initially
Basically, in my project, I will have a struct model as follows:
1 2 3 4 5 6 7 8 | struct User { var id: String var name: String var dateOfBirth: Date var city: String var email: String } |
And normally, when debugging, we will use the following func to print out information about the object including its values. For example, I will create a user as follows:
1 2 | let user = User(id: "1", name: "Dung", dateOfBirth: "13/08/1999", city: "HN", email: " [email protected] ") |
After that, I will print out that user using print (….)
1 2 | print("=Data: ", user) |
The output will now be:
For example, we want to hide the user’s email and dateOfBirth information when sending the log to the server or printing the log to the console, but for now, the data is still exposed, which can cause risks in project. For example, we use Sentry to send log up for statistics and tracking data, we will use a func as follows:
1 2 3 4 | func logError(_ description: String, userInfo: Any...) { // ... } |
We can use the following:
1 2 3 | let user = User(id: "1", name: "Dung", dateOfBirth: "13/08/1999", city: "HN", email: " [email protected] ") logError("User data: ", user) |
Let’s take a look at the log below:
1 2 3 4 5 6 7 | ▿ Your_App.User - id: "1" - name: "Dung" - dateOfBirth: "13/08/1999" - city: "HN" - email: " [email protected] " |
At this point, all user data is logged, although one of them is not strictly necessary in the case of tracking. So how can we hide the user’s information without needing or wanting to debug, log out?
Solution
Since version swift 5.1, we have added a name that is: Property Wrappers. You can read more here By using Property Wrappers, we will add an extra layer to hide information that we do not want it to be saved, debugged … Below will be the paragraph The code we need to add in the project:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | @propertyWrapper struct IgnoreLog<Value>: CustomStringConvertible, CustomDebugStringConvertible, CustomLeafReflectable { var wrappedValue: Value init(wrappedValue: Value) { self.wrappedValue = wrappedValue } var description: String { return "**hidden**" } var debugDescription: String { return "**hidden**" } var customMirror: Mirror { return Mirror(reflecting: "**hidden**") } } |
The above code does not handle anything too complicated, it simply helps to ensure that whenever we try to use the print function, debugPrint, dump the data of that object, it is hidden. its value is “hidden” instead.
Next, for whatever properties we want to hide, we will prepend the LoggingExcluded prefix. For example, I will hide city and email, this time the model will edit as follows:
1 2 3 4 5 6 7 8 | struct User { var id: String var name: String var dateOfBirth: String @IgnoreLog var city: String @IgnoreLog var email: String } |
Let’s try to print it out together
1 2 3 | let user = User(id: "1", name: "Dung", dateOfBirth: "13/08/1999", city: "HN", email: " [email protected] ") print("=Data: ", user) |
The result now:
1 2 3 4 5 6 7 8 9 10 11 12 | // print User(identifier: "1", _name: "Dung" _dateOfBirth: "13/08/1999", _city: **hidden**, _email: **hidden**) // debugPrint Your_App.User(identifier: "1", _name: "Dung" _dateOfBirth: "13/08/1999", _city: **hidden**, _email: **hidden**) // dump ▿ Your_App.User - identifier: "1" - _name: Dung - _dateOfBirth: "13/08/1999" - _city: **hidden** - _email: **hidden** |
Conclusion
The above is an idea to hide information after learning and reading about Property Wrapper, hope it will be useful to you. Thank you.