I am storing the unicode character in the following form in my Parse.com database.
The results I am getting are these
This is how I am fetching the results
if let objects = objects as? [PFObject] {
for object in objects {
println(object.objectId)
let pf = object as PFObject
self.question = pf["Question"] as String
}}
and I am storing self.question in a UILabel
How can I show these the unicode characters in simulator as well.
The only way out is directly store the characters instead of unicode of characters in the Parse database. It supports UTF-8 characters.
Related
noob swift guy here.
I have this UITextView where the user writes something. I need to store his "note" to the database with all the formated text in it. That means if it has bold, I need to display it as bold later.
This text should be stored in local Realm Swift Database. Any solutions how can I achieve that? I head about "Markdown", but I didn't understand how can that be useful.
Much thanks! Have a great day!
Realm only stores ascii text and cannot directly store any formatting properties like BOLD, and that's true for most databases.
If you want to store formatted strings, one option is to archive it to a Data type, which Realm fully supports. Then, when reading data back in, unarchive it from Data back to a formatted string. (formatted strings are often called Rich Text or in code: attributedStrings)
The below code is macOS but iOS will be similar
A quick example - here's a class to hold a some attributed string data
class MyAttrStringClass: Object {
#Persisted var attrStringData: Data!
}
Suppose we have a (rich) text field with the following text
Hello, World
To store the class with the attributed string in Realm:
let s = self.myRichTextField.attributedStringValue
let data = try! NSKeyedArchiver.archivedData(withRootObject: s, requiringSecureCoding: false)
let myObject = MyAttrStringClass()
myObject.attrStringData = data
try! realm.write {
realm.add(myObject)
}
then when reading back from Realm and displaying the attributed string in that same field
let myObject = realm.objects(MyAttrStringClass.self).first!
let data = myObject.attrStringData!
let s = try! NSKeyedUnarchiver.unarchivedObject(ofClass: NSAttributedString.self, from: data)
self.myRichTextField.attributedStringValue = s!
Note: there's no error checking in the above. Please protect your code by safely unwrapping optionals.
I have Swift code which parses an LLDP (link layer discovery protocol) frame, including a field that can be arbitrarily vendor-defined. Sometimes it's a String. Sometimes its an arbitrary data structure.
Here's how I take the data and force it into a String with .utf8 encoding.
let ouiString = String(data: data[data.startIndex + 6 ..< data.startIndex + 2 + tlvLength], encoding: .utf8) ?? ""
Here's the resulting data structure (part of an enumeration with an associated value). "ouiString" above is now in the "info: String" field at the end.
case ouiSpecific(oui: String, subType: Int, info: String)
Here's how I generate a description:
case .ouiSpecific(let oui, let subType, let info):
return "OUI \(oui) subType \(subType) \(info)"
Here's an example of the description where the original data was not a String. The non-displayable characters are shown in a way I find acceptable.
(lldb) po value.description
"OUI 00:12:0f subType 5 \0\u{11}\0\u{11}\0\u{11}\0\u{11}\0\u{11}"
Here's how I try to display it in a SwiftUI List:
List(lldp.values, id: \.self) { value in
Text(value.description)
}
And here's an image of the resulting display in SwiftUI. The info field with all the escaped non-displayable characters are not shown.
How can I display the field in a SwiftUI Text View with the non-displayable characters escaped like in the "po" output?
You can use Unicode.Scalar method escaped(asASCII: Bool) to convert unprintable characters to string:
func escaped(asASCII forceASCII: Bool) -> String
Scalar values representing characters that are normally unprintable or
that otherwise require escaping are escaped with a backslash.
extension StringProtocol {
var asciiEscaped: String {
unicodeScalars.map{$0.escaped(asASCII: true)}.joined()
}
}
Playground testing:
let str = "\0\u{11}\0\u{11}\0\u{11}\0\u{11}\0\u{11}"
print(str.asciiEscaped)
This will print:
\0\u{11}\0\u{11}\0\u{11}\0\u{11}\0\u{11}
I wanted to replace the first character of a String and got it to work like this:
s.replaceSubrange(Range(NSMakeRange(0,1),in:s)!, with:".")
I wonder if there is a simpler method to achieve the same result?
[edit]
Get nth character of a string in Swift programming language doesn't provide a mutable substring. And it requires writing a String extension, which isn't really helping when trying to shorten code.
To replace the first character, you can do use String concatenation with dropFirst():
var s = "πhello world!"
s = "." + s.dropFirst()
print(s)
Result:
.hello world!
Note: This will not crash if the String is empty; it will just create a String with the replacement character.
Strings work very differently in Swift than many other languages. In Swift, a character is not a single byte but instead a single visual element. This is very important when working with multibyte characters like emoji (see: Why are emoji characters like π©βπ©βπ§βπ¦ treated so strangely in Swift strings?)
If you really do want to set a single random byte of your string to an arbitrary value as you expanded on in the comments of your question, you'll need to drop out of the string abstraction and work with your data as a buffer. This is sort of gross in Swift thanks to various safety features but it's doable:
var input = "Hello, world!"
//access the byte buffer
var utf8Buffer = input.utf8CString
//replace the first byte with whatever random data we want
utf8Buffer[0] = 46 //ascii encoding of '.'
//now convert back to a Swift string
var output:String! = nil //buffer for holding our new target
utf8Buffer.withUnsafeBufferPointer { (ptr) in
//Load the byte buffer into a Swift string
output = String.init(cString: ptr.baseAddress!)
}
print(output!) //.ello, world!
In order to convert a String instance to a Data instance in Swift you can use data(using:allowLossyConversion:), which returns an optional Data instance.
Can the return value of this function ever be nil if the encoding is UTF-8 (String.Encoding.utf8)?
If the return value cannot be nil it would be safe to always force-unwrap such a conversion.
UTF-8 can represent all valid Unicode code points, therefore a conversion
of a Swift string to UTF-8 data cannot fail.
The forced unwrap in
let string = "some string .."
let data = string.data(using: .utf8)!
is safe.
The same would be true for .utf16 or .utf32, but not for
encodings which represent only a restricted character set,
such as .ascii or .isoLatin1.
You can alternatively use the .utf8 view of a string to create UTF-8 data,
avoiding the forced unwrap:
let string = "some string .."
let data = Data(string.utf8)
After already having parsed my data through swiftyjson I am looking to display the parsed information in a uitableview. Let's say I have a list of names that I parsed out of the json file. I would like those names to display each in their own respective cells to allow the user to view them all.
I would also assume that if they selected the selected cells which are being displayed strings now after being parsed that I can actually have those stored into a core data object storing them as returnable strings? The thing is I used the .append function onto an array that I created we'll call names = [String]() to actually allow the values to actually come in order for the cells.
But when doing this I noticed a huge spike in cpu usage doing this as it keeps appending them in order lets say first name is matt second name is john and so forth then it creates a new situation of the array every time. so the first time it reads just matt then the next println would print out matt, john then the next one prints out matt, john, tom and so forth until the list of json names is completed.
If I have 500 names or more it takes the cpu awhile to process all those names into the array. I know there has to be another way but all references I see all use the .append method. So my code would be names.append(Name). Name is a parsed string from swiftyjson. From there I am actually able to populate the tableview which is fine it displays correctly in the end but it takes the device awhile to populate as it first needs to process adding all 500 names each time the parse is called. I am hoping to allow the 500 names be rechecked every time in case new ones have been added. This all stores currently as a local json file already.
The code I am using is below I can figure out the UItableview part but it's more a question of whether appending an array is the best and most efficient way of displaying the parsed data from swiftyjson.
let path = NSBundle.mainBundle().pathForResource("List", ofType: "json")
let jsonData = NSData(contentsOfFile: path!, options: NSDataReadingOptions.DataReadingMappedIfSafe, error: nil)
let json = JSON(data: jsonData!)
for (key, subJson) in json["array"] {
if let Name = subJson["Name"].string {
NameList.append(Name)
println(NameList)
}
}
maybe the Swift map function is more effective
β¦
let json = JSON(data: jsonData!)
var nameList = [String]()
if let subJson = json["array"] as [Dictionary<String,NSObject>]? {
nameList = subJson.map { $0["name"] as! String }
}