Reputation: 649
I´m taking baby steps in iOS development and searching for a method to use logging in iOS.
I found these docs about logging with swift 3 : https://developer.apple.com/documentation/os/logging#1682426
The Docs say that the logs aren´t saved on disk. What is the typical way to get the logs and process the file?
Upvotes: 18
Views: 33356
Reputation: 652
Simple way!
func createLogFile() {
guard let documentsDirectory = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first else {
return
}
let fileName = "\(Date()).log"
let logFilePath = (documentsDirectory as NSString).appendingPathComponent(fileName)
freopen(logFilePath.cString(using: String.Encoding.ascii), "a+", stderr)
}
Now call this method on viewDidLoad
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
createLogFile()
NSLog("First Log")
NSLog("Second Log")
}
}
Goto the simulator application directory and check the logs.
NOTE: Only NSLog will work this way. Print, debugPrint will not work.
Upvotes: 2
Reputation: 67300
The Docs say that the logs aren´t saved on disk. What is the typical way to get the logs and process the file?
I'm not sure if this was true at some point and changed, but the current documentation you linked to does say logs are saved on disk:
This system centralizes the storage of log data in memory and on disk, rather than writing that data to a text-based log file.
Specifically, you can find this table in a recommended article:
You can override the default storage behavior of each log level using tools or custom configuration profiles. For more information on how to do so, see Customizing Logging Behavior While Debugging
Here's an example in the article of how to use the logger (swift):
if #available(OSX 11.0, *) {
// Log a message to the default log and default log level.
let defaultLog = Logger()
defaultLog.log("This is a default message.")
// Log a message to the default log and debug log level
defaultLog.debug("This is a debug message.")
// Log an error to a custom log object.
let customLog = Logger(subsystem: "com.your_company.your_subsystem",
category: "your_category_name")
customLog.error("An error occurred!")
} else {
// Log a message to the default log and default log level.
os_log("This is a default message.")
// Log a message to the default log and debug log level
os_log("This is a debug message.", log: OSLog.default, type: .debug)
// Log an error to a custom log object.
let customLog = OSLog(subsystem: "com.your_company.your_subsystem",
category: "your_category_name")
os_log("An error occurred!", log: customLog, type: .error)
}
As far as I can tell, there's no need to use the other answers (anymore?)
Upvotes: 2
Reputation: 1022
Swift 3.0 version
Create a new swift file "TextLog.swift" in your project
import Foundation
struct TextLog: TextOutputStream {
/// Appends the given string to the stream.
mutating func write(_ string: String) {
let paths = FileManager.default.urls(for: .documentDirectory, in: .allDomainsMask)
let documentDirectoryPath = paths.first!
let log = documentDirectoryPath.appendingPathComponent("log.txt")
do {
let handle = try FileHandle(forWritingTo: log)
handle.seekToEndOfFile()
handle.write(string.data(using: .utf8)!)
handle.closeFile()
} catch {
print(error.localizedDescription)
do {
try string.data(using: .utf8)?.write(to: log)
} catch {
print(error.localizedDescription)
}
}
}
}
Initialize the logger at bottom in the AppDelegate.swift file
var textLog = TextLog()
Use it anywhere in the application like below
textLog.write("hello")
Upvotes: 11
Reputation: 17534
put this file to your project
//
// log.swift
// logtest
//
import Foundation
struct Log: TextOutputStream {
func write(_ string: String) {
let fm = FileManager.default
let log = fm.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("log.txt")
if let handle = try? FileHandle(forWritingTo: log) {
handle.seekToEndOfFile()
handle.write(string.data(using: .utf8)!)
handle.closeFile()
} else {
try? string.data(using: .utf8)?.write(to: log)
}
}
}
var logger = Log()
and if you need something to be logged, just use print function like
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
print("started:", Date(), to: &logger)
return true
}
or
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
print(#file, #function, "my own text", 1, [1,2], to: &logger)
}
in your application's 'Documents' folder you could find 'log.txt' file which you could examine later.
while running my test application twice, the content looks like
started: 2017-06-14 09:58:58 +0000
/Users/ivo_vacek/Documents/logtest/logtest/ViewController.swift viewDidLoad() my own text 1 [1, 2]
started: 2017-06-14 09:59:15 +0000
/Users/ivo_vacek/Documents/logtest/logtest/ViewController.swift viewDidLoad() my own text 1 [1, 2]
if you don't like 'globals' define Log as singletone class
class Log: TextOutputStream {
func write(_ string: String) {
let fm = FileManager.default
let log = fm.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("log.txt")
if let handle = try? FileHandle(forWritingTo: log) {
handle.seekToEndOfFile()
handle.write(string.data(using: .utf8)!)
handle.closeFile()
} else {
try? string.data(using: .utf8)?.write(to: log)
}
}
static var log: Log = Log()
private init() {} // we are sure, nobody else could create it
}
and use it like
print("started:", Date(), to: &Log.log)
Upvotes: 28