Reputation: 6484
I'm getting data from sensors using bluetooth, I want to append the string of data I get to the end of file.
When I tried the regular approach
if let dir = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first {
let path = NSURL(fileURLWithPath: dir).URLByAppendingPathComponent(self.file)
do {
try text.writeToURL(path, atomically: false, encoding: NSUTF8StringEncoding)
}
catch {/* error handling here */}
My app started to slow down until even labels were not updating anymore.
Tried using dispatch_async
to do in background thread but still it was slowing down my app.
What approach should I use? I read sth about stream but failed to find some solutions in swift I could rely on
Upvotes: 3
Views: 7205
Reputation: 2699
update @redent84's, to work in Swift 5
Code:
struct MyStreamer{
lazy var fileHandle = FileHandle(forWritingAtPath: logPath)
lazy var logPath: String = {
let path = NSSearchPathForDirectoriesInDomains(.documentDirectory, .allDomainsMask, true)[0]
let filePath = path + "/log.txt"
if FileManager.default.fileExists(atPath: filePath) == false{
FileManager.default.createFile(atPath: filePath, contents: nil, attributes: nil)
}
print(filePath)
return filePath
}()
mutating func write(_ string: String) {
print(fileHandle?.description ?? "呵呵")
fileHandle?.seekToEndOfFile()
if let data = string.data(using: String.Encoding.utf8){
fileHandle?.write(data)
}
}
}
Usage:
var myStream = MyStreamer()
myStream.write("First of all")
myStream.write("Then after")
myStream.write("And, finally")
Upvotes: 3
Reputation: 854
try to write file like this..
var paths: [AnyObject] = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let filePath = paths[0].stringByAppendingString("/filename.mov")
do
{
try NSFileManager.defaultManager().removeItemAtURL(outputURL)
}
catch
{
error as NSError
}
do {
try text.writeToURL(path, atomically: false, encoding: NSUTF8StringEncoding)
}
I mean to say at last is you have to remove first.. If any query you can ask me
Upvotes: -1
Reputation: 19239
Probably your bluetooth is reading data faster than you are performing your file operations. You can optimize it by appending the text to the file instead of reading all the content on each write operation. You could also reuse the file handler between writes and keep the file open.
This sample is extracted from this answer:
struct MyStreamer: OutputStreamType {
lazy var fileHandle: NSFileHandle? = {
let fileHandle = NSFileHandle(forWritingAtPath: self.logPath)
return fileHandle
}()
lazy var logPath: String = {
let path : NSString = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first!
let filePath = (path as NSString).stringByAppendingPathComponent("log.txt")
if !NSFileManager.defaultManager().fileExistsAtPath(filePath) {
NSFileManager.defaultManager().createFileAtPath(filePath, contents: nil, attributes: nil)
}
print(filePath)
return filePath
}()
mutating func write(string: String) {
print(fileHandle)
fileHandle?.seekToEndOfFile()
fileHandle?.writeData(string.dataUsingEncoding(NSUTF8StringEncoding)!)
}
}
Then, you can create a single streamer and reuse it in different writes:
var myStream = MyStreamer()
myStream.write("First of all")
myStream.write("Then after")
myStream.write("And, finally")
In this case, you have the bonus that MyStreamer
is also a OutputStreamType
, so you can use it like this:
var myStream = MyStreamer()
print("First of all", toStream: &myStream )
print("Then after", toStream: &myStream)
print("And, finally", toStream: &myStream)
Finally I'd recommend you to move 'log.txt' string to a instance variable and pass it as a constructor parameter:
var myStream = MyStreamer("log.txt")
More info about file handler in the Apple Docs.
Upvotes: 9