first I would like to start with my current situation:
1) Current Situation:
I have a text file (data.rtf) I have also tried and am willing to use .plist or any other format to get a result.
I have been trying to read ANY data from this file, and show that data on a Label.
I have tried pre-populating the file, saving to the file before reading from it, and even just checking that the file exists, but every attempt has failed.
For 3 days I have searched various instructions and tutorials on how to do what is usually a fairly simple feature. I already did it using Objective-C, but I am new to Swift and unfortunately have to use it for this assessment and I am stuck.
2) Obstacles:
Every example I have looked at so far has been rejected by XCode as erroneous, ether for using terms that are no longer accepted like:
let path = (NSTemporaryDirectory() as NSString).stringByAppendingPathComponent("image.png")
Or lines that flat out do not work at all like:
let client = arrayClients[0]
DisplayLabel.text = "\(client.ob("FirstName")!) \(client.objectForKey("LastName")!)"
//DisplayLabel.text = client. <- this part doesn't work
Every case either ends with code that is too out of date to work, or is too butchered after updating it to the replacements recommended to still work. The only cases where I have got the code to even build (removing syntax errors) has logical errors where the results either are nothing, or it crashes, most commonly with:
"NSCocoaErrorDomain Code = 260 "The file "data.rtf" couldn't be opened because there is no such file." "No such file or directory"
I think, even though the file exists in my XCode project, it is being searched for in the iPhone simulator, and for some reason it does not exist there. This is only a theory, and I have no idea how to fix that. I never encountered this problem when doing the same thing using Objective-C, where if I made a file and path to it, it worked, but for Swift it simply refuses to
3) The Code:
At this point, I am more interested in a code that works, than a fix to mine that does not, as mine has become so butchered in my attempts to solve this (as well as other XCode update related issues) that it is barely fit for purpose even if I get around this obstacle, but in case it helps, I will provide "some" of the different attempts I have pulled
// The "file not found code" :
let path = (NSTemporaryDirectory() as NSString).appendingPathComponent("data.rtf")
do {
// Get the contents
let contents = try NSString(contentsOfFile: path, encoding: String.Encoding.utf8.rawValue)
print(contents)
DisplayLabel.text = contents as String?
}
catch let error as NSError {
print("Ooops! let path = (NSTemp... did not work: \(error)")
}
// Another variation with same result:
let file: FileHandle? = FileHandle(forReadingAtPath: "DataFile.plist")
if file != nil {
// Read all the data
let data = file?.readDataToEndOfFile()
// Close the file
file?.closeFile()
// Convert our data to string
let str = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
print(str!)
DisplayLabel.text = str as String?
}
else {
print("Ooops! Something went wrong!")
}
// A version where the final line throws a (syntax -> Edit -> Fatal) error I have been unable to solve:
var dictClients = [String:String]()
var arrayClients = NSMutableArray()
let path = Bundle.main.path(forResource: "data", ofType: "rtf")
let filemgr = FileManager.default
if filemgr.fileExists(atPath: path!) {
do {
let fullText = try String(contentsOfFile: path!, encoding: String.Encoding.utf8)
let readings = fullText.components(separatedBy: "\n") as [String]
for i in 1..<readings.count {
let clientData = readings[i].components(separatedBy: "\t")
dictClients["FirstName"] = "\(clientData)"
arrayClients.add(dictClients)
}
} catch {
print("error: \(error)")
}
}
let client = arrayClients[0]
//DisplayLabel.text = client.
//DisplayLabel.text = "\(client.ob("FirstName")!) \(client.objectForKey("LastName")!)"
// -Edit - I was able to fix the Syntax error with the below, but got a logic error instead
DisplayLabel.text = "\((client as AnyObject).object(forKey:"FirstName")!) \((client as AnyObject).object(forKey:"LastName")!)"
-- Edit New error --
"fatal error: unexpectedly found nil while unwrapping an Optional value"
I Hope this has somehow been clear, and I appreciate any help in resolving the problem. I have been working on this application since Thursday, and this particular issue since Sunday, with very little sleep or rest, even more computer is struggling to keep running under the strain and my focus is not as strong and I may not be as coherent as I think, so forgive any obvious mistakes I have made or poor communication I may be using.
Thanks in advance
The main issue is that you cannot load rich text (RTF) formatted text into String
. The Cocoa equivalent to RTF is NSAttributedString
.
Load the RTF as Data
, create an NSAttributedString
and get the plain text with the string
property.
var arrayClients = [[String:String]]() // do not use NSMutableArray in Swift
var dictClients = [String:String]()
if let url = Bundle.main.url(forResource:"data", withExtension: "rtf") {
do {
let data = try Data(contentsOf:url)
let attibutedString = try NSAttributedString(data: data, documentAttributes: nil)
let fullText = attibutedString.string
let readings = fullText.components(separatedBy: CharacterSet.newlines)
for line in readings { // do not use ugly C-style loops in Swift
let clientData = line.components(separatedBy: "\t")
dictClients["FirstName"] = "\(clientData)"
arrayClients.append(dictClients)
}
} catch {
print(error)
}
}
However for that kind of data structure RTF is not appropriate. Better use JSON or property list.