Swift is an open-source programming language for Apple’s iOS and OS X. It offers a powerful, expressive syntax that allows developers to write code more quickly than with Objective-C. However, the language has one major drawback – it doesn’t offer any logging functionality of its own.
The ios logging best practices is a powerful input-agnostic swift logging framework made to speed up development. It is designed to be flexible and easy to use for debugging and profiling.
Atlantis is a strong logging framework that I built for daily usage, such as enterprise development for ambitious start-ups or fast prototyping APIs. It is type agnostic, which means you can give it anything from strings to customobjects that you created yourself… and it will beautifully print all of the data inside that object or anything else in general. It’s designed to be very readable and simple to use.
Installation
Make a note of it in your podfile…
# for Swift 4.0 pod ‘Atlantis’, :git => ‘https://github.com/aaronjsutton/Atlantis.git’, :branch =>’swift-4-patch’ # for Swift 3.0 pod ‘Atlantis’, :git => ‘https://github.com/aaronjsutton/Atlantis.git’, :branch => ‘ # for ‘Atlantis’ Swift 2.3 pod, :git => ‘https://github.com/DrewKiino/Atlantis.git’, :branch =>’swift2.3′
Then do a pod install, and you’re done!
Logs that are unique
This contains the date, source, function, and line number of the log, as well as the value’s actual type.
The date is formatted as follows: month, date, year, hour, and finally time of day.
/ You don’t need to do anything with this since the variable is set in the file. Let’s say log equals Atlantis. Logger() / Let’s start logging some information. “Hello, World!” log.verbose(“Hello, World!”) “Hello, World!” log.info(“Hello, World!”) “Hello, World!” log.warning(“Hello, World!”) “Hello, World!” log.debug(“Hello, World!”) “Hello, World!” log.error(“Hello, World!”)
The following is printed…
Printing with Impact
Atlantis is designed to print things in a beautiful way.
– text alignment that is correct
Atlantis aligns its logs automatically depending on prior alignments. However, by changing this variable, you may alter the settings.
Atlantis. Configuration.alignmentThreshold
which is set to 5 by default.
– further options
Any optionals will be securely unwrapped by Atlantis.
log.warning(doIExist) / displays ‘nil’ if doIExist: String? = nil
– null strings
Empty strings will be visibly printed by Atlantis.
log.warning(emptyString) / outputs “” let emptyString: String = “”
– kinds that are indigenous
if string = “Hello, World” if string = “Hello, World” if string = ” Let’s say int is 123. let float = 12.3 let double = 12.3 let bool = true / you can log one value or two values. debug(string) / or, in this case, all of them, log. 123 12.3 12.3 true debug(string, int, double, float, bool) / prints “Hello, World” / first one “Hello, World”
– arrays
Let numbers = [123, 1234, 12345] be an array of ints. / outputs [ 123, 1234, 12345 ] in log.debug(numbers) Let’s try arrays of arrays and see what happens. [[1, 2, 3], [4, 5]] Array [ [ 1, 2, 3 ], [ 4, 5 ] ] prints log.debug(numberArray)
Dictionary dictionaries
/ let’s move on to dictionaries… dictionary: [AnyObject] as a string = [ “quote”: “Is it better to have loved than never to have loved?” ] / prints log.debug(dictionary) [ “quote”: “Isn’t it better to have loved than never to have loved?” ] / NSDictionary kinds, perhaps? dictionary = NSDictionary; var dictionary = NSDictionary; var dictionary = NSDi () key: “question”), dictionary.updateValue(“will this work?”, dictionary.updateValue(“will this work?”, dictionary.updateValue(“will this work / prints log.debug(dictionary) [ “question”: “Is this going to work?”] / Let’s suppose we received two response objects from the server; both are identical, but one is missing data. responses.map is a map that shows how many people have reacted to a / prints log.debug($0) “success” 200, “response”: null, “success” 200, “response”: null, “success” 200 / Regardless of missing or empty values, Atlantis will print all of the object’s keys, including null if necessary.
– objects
/ Now it’s time to have some fun. log.debug(UIColor()) / native Foundation (ex: UIView, UIColor, etc.) / native / prints NSObjects let dog = Dog() log.debug public class Dog: NSObject var name = “Doug” (dog) / outputs “Doug” is the name of the character. What about objects that don’t have any native subclasses? let customObject = CustomObject() log.debug(customObject) / outputs the var id: Int = 123 var name: String = “Ben” public class CustomObject var id: Int = 123 var name: String = “Ben” “name”: “Doug” / “id”: 123, “name”: “Doug” No way? Hahahahahahahahahahahahahahahaha / So, how about custom objects that include custom objects? let parentObject = ParentObject() log.debug(parentObject) / prints “id”: 456, “name”: “Tammy” “customObject”: “id”: 123, “name”: “Doug” That’s correct. / Okay, custom objects with a custom object array. let parentObject = ParentObject() log.debug(parentObject) / prints var id: Int = 456 var name: String = “Tammy” var customObjects: [CustomObject] = [CustomObject(), CustomObject()] var customObjects: [CustomObject] = [CustomObject(), CustomObject()] var customObjects: [CustomObject] = [CustomObject(), CustomObject()] var customObjects: [CustomObject] = [CustomObject “id”: 456, “name”: “Tammy” “customObjects”: [ “id”: 123, “name”: “Doug,” “id”: 123, “name”: “Doug,” “id”: 123, “name”: “Doug,” “id”: 123, “name”: “Doug,” “id”: 123, “name”: “Doug,” “id”: Are you unimpressed? parentObject1 = ParentObject() parentObject2 = ParentObject() / one of its children has a dictionary log.debug(parents) / outputs [ParentObject] = [parentObject1, parentObject2] [ “id”: 456, “name”: “Tammy” “customObjects”: [ “id”: 123, “name”: “Doug,” “id”: 123, “name”: “Doug,” “id”: 123, “name”: “Doug,” “id”: 123, “name”: “Doug,” “id”: 123, “name”: “Doug,” “id” }, “id”: 456, “name”: “Tammy” “customObjects”: [ “id”: 123, “name”: “Doug”], “id”: 123, “name”: “Doug” “dictionary”: [ “likes”: “baseball”, “dislikes”: “pad thai” / The logging in Atlantis is endlessly and ambiguously recursive, and it supports nearly any data types, including arrays, dictionaries, and objects inside objects. 👍🏼
– Structs
/ Excellent!! Now we’ll move on to some additional stand-alone yet desperately required kinds. struct Struct var name: String = “Bob the Builder” var skills: [String] = [“structures, buildings”] struct Struct var name: String = “Bob the Builder” struct Struct var name: String = “Bob the Builder” struct Struct var name: String = “Bo “skills”: [ “structures, buildings” ], “name”: “Bob the Builder” / log.debug(Struct()) / prints “skills”: [ “structures, buildings” ], “name”: “Bob the Builder”
– Enum
case enum ErrorType Extremely serious situation Casual in a moderate instance allow for type: ErrorType = ErrorType = ErrorType = ErrorType = Er log.debug(type) / prints a serious message Another example is severe. log.debug(ErrorType.Moderate) / prints log.debug(ErrorType.Casual) Moderately informal
Handling Errors
Atlantis will publish all mistakes in this manner.
[ViewController.swift/viewDidLoad()/line:98] [ViewController.swift/viewDidLoad()/line:98] [ViewController.swift/viewDidL ,,,,,,,,,, “”localizedDescription” : “The operation could not be finished.” code” : 404, “localizedDescription” : “The operation could not be completed.” (Hello, World! 404 error.)”, “domain” : “Hello, World!”, “userInfo” : “Hello, World!” “:: “discovered” as a “error” and “syntax” as a “note”
It will parse the NSError object’s localized description, error code, domain, and user information automatically.
The default value for Atlantis.Configuration.highlightsErrors is false.
Atlantis prints all logs in white by default, or in color if colored logging is enabled. If you enable error highlighting, however, it will always show mistakes regardless of the settings you provide.
Atlantis.Configuration.filteredErrorCodes
Atlantis is capable of filtering errors depending on their error code. For example, suppose you have a function that makes requests to the network, and you set it up such that it may only send one request at a time, canceling the previous one. Some APIs, on the other hand, are outside our control and will generate errors without your consent.
Let’s say you wish to exclude error number -1099 / offline error from your search.
Atlantis.Configuration.filteredErrorCodes.append(-1099) Let’s call a function that throws errors, but one of them is something we wish to filter out. method() error in log.error(error) / is it possible to get a 404 or a -1099? / The error will only be printed if the error code is 404.
If the method now returns a -1099 error, Atlantis will ignore it!
.Tap
Tap is an Atlantis extension that enables you to print like you normally would, but returns the value of the input instead.
let addXY = log.tap.debug(add(3, 5)) func add(x: Int, y: Int) -> Int return x + y / displays the number 8 and assigns it to the variable addXY
.Verbose and other common extensions are also included. Tap
Promises Compatibility
Using PromiseKit in particular…
Promise func promise() -> Promise func promise() -> Promise func promise() -> come back fulfill(“Hello from server!”) fulfill(“Hello from server!”) fulfill(“Hello from server!”) fulfill(“Hello from server!”) fulfill(“Hello from server!”) fulfill(“Hello from server!”) fulfill(“Hello from server promise() is a function that returns a promise. then log.tap($0) is used. then respond in / blah blah blah blah yada blah blah blah blah blah blah bla while fulfilling the promise, catch log.error($0) / outputs “Hello from server!”
Take note of this. Tap can only accept one input at a time.
Configuration
Levels
Default value for Atlantis.Configuration.logLevel is.Verbose.
Verbose, Info, Warning, Debug, Error, and None are the five log levels, in order of importance.
If you set the log level to Debug, For example, Atlantis will only output logs with the Debug and Error levels.
The log level has been set to. Atlantis will skip all log execution if none is specified. When the app is moved to production, I suggest utilizing this.
Information from the source
showExtraInfo.Atlantis.Configuration.default = true
By setting this option to false, you may also conceal the source information.
Coloring
Atlantis can offer complete color customisation.
Atlantis.Configuration.hasColoredLogs / default false Atlantis.Configuration.hasWhiteBackground / default false Atlantis.Configuration.hasColoredLogs / default false Atlantis.Configuration.hasColoredLogs / default false Atlantis.Configuration.hasColoredLogs / default false At coloredLogLevels.configuration.default [.Verbose,.Info,.Warning,.Debug,.Verbose,.Info,.Warning,.Warning,.Warning,.Warning,.Warn .Error] Atlantis uses a Tuple initializer. Atlantis is the value of Configuration.logColors.info. XCodeColor(fg: (Int, Int, Int)>, bg: (Int, Int, Int)>) / just the foreground Atlantis is set using UIColor. Atlantis is the value of Configuration.logColors.info. XCodeColor is a color code (fg: UIColor) / or set both the foreground and background Atlantis using UIColor. Atlantis = Configuration.logColors.debug XCodeColor is a color code (fg: UIColor, bg: UIColor)
Atlantis does not publish its logs in color by default. If you want colors, you’ll have to do so during the startup process.
To enable log colors, you must first download and install the xcode package manager Alcatraz and then activate it in xcode. After that, open the package manager and install XCodeColors.
Afterword
To Do
- build a framework for logging
- customize the color scheme
- When using a device, print to a text file.
- display json types from server replies in a nice way
GitHub
https://github.com/DrewKiino/Atlantis
The swift cannot find logger in scope is a problem that has been present for a while. This framework was made to fix the issue.
Related Tags
- swift logging example
- ios logging framework
- cannot find ‘logger’ in scope
- swift logger
- swift log to file