Reputation: 825
I'm trying to retrieve a text file from a URL and then process that text file in the swift Data form. It's like a CSV file but uses "|" for the column delimiter and "}" for the row delimiter.
I'd like to remove the first "line" up to a "}" character (my line delimiter is a "}" so that I can cycle through the file until it's empty.
However NSURLRequest returns an immutable Swift Data object.
I guess I can copy it into a mutable copy but I prefer it if I could persuade NSURLRequest to return a mutable Data object. Is that possible?
My URL request looks like this:
func load(url: String) {
debugPrint(#function)
let url = URL(string: url)!
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
self.handleClientError(error: error)
return
}
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
self.handleServerError(error: response)
return
}
debugPrint("data got")
self.dataGot(data: data!)
DispatchQueue.main.async {
self.loadingDelegate!.stockLoadComplete()
}
}
task.resume()
}
currently I'm creating a string from the entire file and doing some string operations to split rows and columns:
let asString = String(data: data, encoding: String.Encoding.utf8)
let rows = asString!.components(separatedBy: "}")
for row in rows {
self.addPriceLine(line: row)
}
This approach is failing with a malloc error (after successfully processing a few hundred rows) so I suspect that I'm going down the wrong road somehow.
Is there a "good" or recommended approach? Using just a Data object seems a lot more elegant to me.
Advice appreciated.
Upvotes: 0
Views: 222
Reputation: 825
OK so I solved the problem.
I was getting a runtime malloc error which made me think there was some problem with the Data buffer or its conversion to a string.
I wandered if it was something failing with memory allocation in the closure so I put the gotData() processing onto the main dispatch queue. Voila - the malloc went away.
Clearly there are limits to what you should do in the closure, rather than the main dispatch queue and I guess I was misusing the approach.
:)
let task = URLSession.shared.dataTask(with: url) { data, response, error in
if let error = error {
self.handleClientError(error: error)
return
}
guard let httpResponse = response as? HTTPURLResponse,
(200...299).contains(httpResponse.statusCode) else {
self.handleServerError(error: response)
return
}
debugPrint("data got")
DispatchQueue.main.async {
self.dataGot(data: data!)
self.loadingDelegate!.stockLoadComplete()
}
}
Upvotes: 0