This question already has answers here:
Swift String Interpolation displaying optional?
(4 answers)
Closed 5 years ago.
class func shareString(title : String, array: [AnyObject]) -> String {
var strValue: String!
//strValue = "\(title)"
for i in 0...array.count-1 {
let share:[String: String?] = array[i] as! [String : String?]
strValue = "\n\n \(strValue), \n\n \(share["title"]) \n\n\(share["value"])"
}
return strValue!
}
//Optional("\n\n Optional(\"\\n\\n nil, \\n\\n Optional(Optional(\\\"\\\\n LayFlat\\\")) \\n\\nOptional(Optional(\\\"252.0\\\"))\"), \n\n Optional(Optional(\"\\n Die Diameter\")) \n\nOptional(Optional(\"25.0\"))"),
Optional(Optional("\n Output"))
Optional(Optional("6.42096"))
When you subscript it will already return optional and you are setting dictionary with value String? means you are getting optional twice also specifying array of AnyObject make it array of [[String:String]] so no need to cast it letter again. Also initialized the strValue with empty string.
var strValue = ""
if let dicArray = array as? [[String:String]] {
for dic in dicArray {
if let title = dic["title"], let value = dic["value"] {
strValue += "\n\n \(title) \n\n\(value)"
}
}
}
for i in 0...array.count-1 {
let share:[String: String?] = array[i] as! [String : String?]
if let title = share["title"], let value = share["value"]{
print("title: \(title) , Value: \(value)")
//output: title: 252.0 , Value: Die Diameter
}
}
Use optional chaining like bellow
strValue = "\n\n (strValue ?? ""), \n\n (share["title"] ?? "")
\n\n(share["value"] ?? "")"
Use force unwrap variable if it has value
strValue = "\n\n (strValue!), \n\n (share["title"]!)
\n\n(share["value"]!)"
Related
I have a database in firebase which looks as follows:
I need to get the values of nameID, tutorID, and imageURL and assign them to variables in Swift 4. Here is what I have so far in XCode:
let ref = Database.database().reference().child("students").child("student1")
ref.observe(.childAdded, with: { (snapshot) in
print(snapshot)
guard let dictionary = snapshot.value as? [String : AnyObject] else {
return
}
print (dictionary)
let Obj = studentInformation(nameID: " ", tutorID: " ", imageURL: " ")
Obj.imageURL = dictionary["photoID"] as? String
Obj.nameID = dictionary["nameID"] as? String
Obj.tutorID = dictionary["tutorID"] as? String
self.studentInfo.append(Obj)
}, withCancel: nil)
For the studentInformation class, I have declared it as such:
class studentInformation {
var nameID: String?
var tutorID: String?
var imageURL: String?
init(nameID: String?, tutorID: String?, imageURL: String?) {
self.nameID = nameID
self.tutorID = tutorID
self.imageURL = imageURL
}
}
I can't seem to get it to work correctly, as it's able to get the values from the database, but it is not able to assign it to the local variables I have in XCode. Any help would be appreciated. Thanks in advance
Create an optional initializer for in the Object and determine which variables should be optional (ex: only the imageURL is optional in the example below, and the nameID and tutorID have to be Strings otherwise the init will return nil):
init?(dictionary: [String : Any]) {
guard let nameId = dictionary["nameID"] as? String,
let tutorID = dictionary["tutorID"] as? String else { return nil }
let imageURL = dictionary["imageURL"] as? String
self.init(nameID: nameID, tutorID: tutorID, imageURL: imageURL)
}
Then, in the Firebase listener you can create the object like this:
// Returns Optional(obj)
let obj = studentInformation(dictionary: dictionary)
or
// Add object to array
if let obj = studentInformation(dictionary: dictionary) { self.studentInfo.append(obj) }
The offending element is the
let mSSIDDATA = SSIDDict["SSIDDATA"]
field. If I leave it as it is, it prints out to the log window as shown here.
Looking up SSID info for en0 SSIDDict Values: ["SSID": SKYF7BFF,
"BSSID": 7c:4c:a5:c:8b:15, "SSIDDATA": <534b5946 37424646>]
mSSID: SKYF7BFF
mBSSID: 7c:4c:a5:c:8b:15
mSSIDDATA: <534b5946 37424646>
SSID: SKYF7BFF
BSSID: 7c:4c:a5:c:8b:15
SSIDDATA: <534b5946 37424646>
=========
However - It doesn't print out into the UITextField in the iOS interface. The other two do, but this third one doesn't, and I can't figure out why.?
If I change the [String : Any] to [String : AnyObject] it creates another whole set of warnings and errors.
So basically, how do I convert that mSSIDDATA to a string that the UITextField can handle?
guard let SSIDDict: [String : Any] = (unwrappedCFDictionaryForInterface as NSDictionary) as? [String: AnyObject] else {
print("System error: interface information is not a string-keyed dictionary")
return false
}
print("SSIDDict Values: \(SSIDDict)")
let mSSID = SSIDDict["SSID"] as? String
let mBSSID = SSIDDict["BSSID"] as? String
let mSSIDDATA = SSIDDict["SSIDDATA"] //as? String
print("mSSID: \(mSSID ?? "")")
vSSID.text = mSSID
print("mBSSID: \(mBSSID ?? "")")
vBSSID.text = mBSSID
print("mSSIDDATA: \(mSSIDDATA ?? "")")
vSSIDDATA.text = mSSIDDATA as? String
for d in SSIDDict.keys {
print("\(d): \(SSIDDict[d]!)")
}
}
return true
}
As the name mSSIDDATA implies and the output <...> indicates the type of the value is Data
if let mSSIDDATA = SSIDDict["SSIDDATA"] as? Data {
print(String(data: mSSIDDATA, encoding : .utf8)!) // SKYF7BFF
}
Practically it's the Data representation of the mSSID string value.
Your „SSIDDATA” is most likely od Data type - you need to convert it to String. You can USD the init(data:encoding:) on String to achieve this.
I'm using sqlite file to get the diaryEntriesTeacher from the authorId. it generates the following object of authorId when I print the variable authorId is nil
Code :-
func applySelectQuery() {
checkDataBaseFile()
objFMDB = FMDatabase(path: fullPathOfDB)
objFMDB.open()
objFMDB.beginTransaction()
do {
let results = try objFMDB.executeQuery("select * from diaryEntriesTeacher", values: nil)
while results.next() {
let totalCount = results.resultDictionary
let authorId = totalCount?["authorId"]!
print("authorId",authorId)
}
}
catch {
print(error.localizedDescription)
}
print(fullPathOfDB)
self.objFMDB.commit()
self.objFMDB.close()
}
output
This is how you access Dictionary of [AnyHashable : Any]
var dict : Dictionary = Dictionary<AnyHashable,Any>()
dict["name"] = "sandeep"
let myName : String = dict["name"] as? String ?? ""
In your case
let authorId = totalCount?["authorId"] as? String ?? ""
We need to convert the property we are trying to access to AnyHashable before using it.
In your case :
do {
let results = try objFMDB.executeQuery("select * from diaryEntriesTeacher", values: nil)
while results.next() {
let totalCount = results.resultDictionary
let authorId = totalCount?[AnyHashable("authorId")]!
print("authorId",authorId)
}
This is Swift. Use strong types and fast enumeration. Dictionary<AnyHashable,Any> is the generic type of a dictionary and can be cast to <String,Any> as all keys seem to be String.
do
if let results = try objFMDB.executeQuery("select * from diaryEntriesTeacher", values: nil) as? [[String:Any]]
for item in results {
let authorId = item["authorId"] as? String
let studentName = item["studentName"] as? String
print("authorId", authorId ?? "n/a")
print("studentName", studentName ?? "n/a")
}
}
....
I'm updating my code from Swift 2.3 to Swift 3, and I am facing these difficulties to get an array key value from a loop in Swift:
var countryarray = NSMutableArray()
self.GetCountriesResult = (responseJSON.objectForKey("GetCountriesResult") as? NSArray)!
for i in 0 ..< self.GetCountriesResult.count {
self.countryarr = self.GetCountriesResult.objectAtIndex(i).objectForKey("countryname") as? String ?? ""
self.countryarray.addObject(self.countryarr)
}
map is better suited than for-in in this case:
guard let json = responseJSON["GetCountriesResult"] as? [String : AnyObject]
else { return }
self.GetCountriesResult = json
let countryArray = self.GetCountriesResult.map {
return $0["countryname"] as? String ?? ""
}
// OR
guard let json = responseJSON["GetCountriesResult"] as? [String : AnyObject]
else { return }
let countries = json.map {
return $0["countryname"] as? String ?? ""
}
Suggestion: Read the following Swift style guides:
https://swift.org/documentation/api-design-guidelines/
https://github.com/raywenderlich/swift-style-guide
https://github.com/linkedin/swift-style-guide
https://github.com/github/swift-style-guide
How could we convert anyobject to string in swift 3, it's very easy in the older version by using.
var str = toString(AnyObject)
I tried String(AnyObject) but the output is always optional, even when i'm sure that AnyObject is not a optional value.
The compiler suggests that you replace your code with:
let s = String(describing: str)
One other option is available if you have a situation where you want to silently fail with an empty string rather than store something that might not originally be a string as a string.
let s = str as? String ?? ""
else you have the ways of identifying and throwing an error in the answers above/below.
Here's three options for you:
Option 1 - if let
if let b = a as? String {
print(b) // Was a string
} else {
print("Error") // Was not a string
}
Option 2 - guard let
guard let b = a as? String
else {
print("Error") // Was not a string
return // needs a return or break here
}
print(b) // Was a string
Option 3 - let with ?? (null coalescing operator)
let b = a as? String ?? ""
print(b) // Print a blank string if a was not a string
Here's a simple function (repl.it) that will mash any value into a string, with nil becoming an empty string. I found it useful for dealing with JSON that inconsistently uses null, blank, numbers, and numeric strings for IDs.
import Foundation
func toString(_ value: Any?) -> String {
return String(describing: value ?? "")
}
let d: NSDictionary = [
"i" : 42,
"s" : "Hello, World!"
]
dump(toString(d["i"]))
dump(toString(d["s"]))
dump(toString(d["x"]))
Prints:
- "42"
- "Hello, World!"
- ""
Try
let a = "Test" as AnyObject
guard let b = a as? String else { // Something went wrong handle it here }
print(b) // Test
try this -
var str:AnyObject?
str = "Hello, playground" as AnyObject?
if let value = str
{
var a = value as! String
}
OR
var a = str as? String