I have a project built in Swift 1.5. When I converted the code to swift 3.0 it started showing me errors in each 'if' statement in below code:
convenience init?(userInfo: [NSObject: AnyObject]) {
guard let statusString = userInfo[ConnectionMessage.StatusKey] as? String else {
return nil
}
guard let status = ConnectionStatus(string: statusString) else {
return nil
}
guard let connectionId = userInfo[ConnectionMessage.ConnectionIdKey]?.longLongValue else {
return nil
}
var ssid = ""
if let newSsid = userInfo[ConnectionMessage.SSIDKey] as? String {
ssid = newSsid
}
var password = ""
if let pw = userInfo[ConnectionMessage.PasswordKey] as? String {
password = pw
}
let buyerName = userInfo[ConnectionMessage.BuyerNameKey] as? String
self.init(status: status, connectionId: connectionId, ssid: ssid, password: password, buyerName: buyerName)
}
The error is
Ambiguous reference to member subscript
I tried the solutions found on StackOverflow but no luck. Please guide.
Change userInfo from [NSObject : AnyObject] to [String : AnyObject]. This assumes all of your ConnectionMessage.xxxKey values are String.
You also need to ensure that the dictionary you pass into the userInfo parameter is actually a dictionary with keys of type String.
Related
This question already has an answer here:
How to subscript a dictionary that is stored inside a dictionary in swift?
(1 answer)
Closed 4 months ago.
I have the following code.
func setUserToken(_ user: NSDictionary) {
self.userId = user["user"]["id"] as! String;
I get the error "Value of type Any has no subscripts". What am I doing wrong?
You need to specify your json before parsing it. Try This:
func setUserToken(_ user: NSDictionary) {
guard let userData = user as? NSDictionary else{return}
guard let user = userData["user"] as? String else{return}
self.userid = user["id"] as? String else{return}
}
The type of any lookup from a NSDictionary is Any. You know (or think you know) it is another dictionary, but Swift does not. You must establish the type before you can do the second lookup.
func setUserToken(_ user: NSDictionary) {
if let userDict = user["user"] as? NSDictionary {
// We now know “user” is a valid key and its value
// is another NSDictionary
if let userId = userDict["id"] as? String {
// We now know “id” is a valid key and its
// value is of type String which has been
// assigned to userId. Now assign it to the
// property
self.userId = userId
return
}
}
// If we get here, something went wrong.
// Assign a reasonable default value.
self.userId = “user unknown”
}
You can do it in a single line using optional chaining and the nil coalescing operator:
self.userId = ((user["user"] as? NSDictionary)?["id"] as? String) ?? “user unknown”
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) }
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 getting this error which I can't figure out how to fix:
Contextual type 'AnyObject' cannot be used with dictionary literal
I've searched on the internet but failed to find an answer. Here's my code:
struct Sweet {
let key:String!
let content:String!
let addedByUser:String!
let itemReft:FIRDatabaseReference?
init (content:String, addedByUser:String, key:String = "") {
self.key = key
self.content = content
self.addedByUser = addedByUser
self.itemReft = nil
}
init (snapshot:FIRDataSnapshot) {
key = snapshot.key
itemReft = snapshot.ref
if let dict = snapshot.value as? NSDictionary, let postContent = dict["content"] as? String {
content = postContent
} else {
content = ""
}
if let dict = snapshot.value as? NSDictionary, let postUser = dict["addedByUser"] as? String {
addedByUser = postUser
} else {
addedByUser = ""
}
}
func toAnyObject() -> AnyObject {
return ["content":content, "addedByUser":addedByUser]
}
The error happens at this line:
return ["content":content, "addedByUser":addedByUser]
I've been following this tutorial iOS Swift Tutorial: Get started with Firebase and an App like Twitter
Thanks for your time!
You have to cast the literal to the desired type
func toAnyObject() -> Any {
return ["content":content, "addedByUser":addedByUser] as Any
}
But - no offense – casting up a specific type to something more unspecific is silly. Why not
func toDictionary() -> [String:String] {
return ["content":content, "addedByUser":addedByUser]
}
I've been struggling on an issue for some time now. I'm wondering why this code :
private func generateIdentity (base64p12 : String, password : String?, url : NSURL) {
let p12KeyFileContent = NSData(base64EncodedString: base64p12, options: NSDataBase64DecodingOptions(rawValue: 0))
if (p12KeyFileContent == nil) {
NSLog("Cannot read PKCS12 data")
return
}
let options = [String(kSecImportExportPassphrase):password ?? ""]
var citems: CFArray? = nil
let resultPKCS12Import = withUnsafeMutablePointer(&citems) { citemsPtr in
SecPKCS12Import(p12KeyFileContent!, options, citemsPtr)
}
if (resultPKCS12Import != errSecSuccess) {
print(resultPKCS12Import)
return
}
let items = citems! as NSArray
let myIdentityAndTrust = items.objectAtIndex(0) as! NSDictionary
let identityKey = String(kSecImportItemIdentity)
identity = myIdentityAndTrust[identityKey] as! SecIdentityRef
hasCertificate = true
print("cert cre", identity)
}
compiles, whereas this other one not :
private func generateIdentity (base64p12 : NSData, password : String?) {
let p12KeyFileContent = NSData(data: base64p12)
let options = [String(kSecImportExportPassphrase):password ?? ""]
var citems: CFArray? = nil
let resultPKCS12Import = withUnsafeMutablePointer(&citems) { citemsPtr in // line with the error
SecPKCS12Import(p12KeyFileContent!, options, citemsPtr)
}
if (resultPKCS12Import != errSecSuccess) {
print(resultPKCS12Import)
return
}
let items = citems! as NSArray
let myIdentityAndTrust = items.objectAtIndex(0) as! NSDictionary
let identityKey = String(kSecImportItemIdentity)
identity = myIdentityAndTrust[identityKey] as! SecIdentityRef
hasCertificate = true
print("cert cre", identity)
}
XCode tells me that :
Cannot convert value of type 'inout CFArray?' (aka 'inout Optional') to expected argument type 'inout _'
I really don't see how the 2 codes are different for the citems variable because what I basically just did was to use a NSData argument for the function, thus bypassing base64 string conversion to NSData.
The error message is super-confusing, but the cause of the error resides here:
SecPKCS12Import(p12KeyFileContent!, options, citemsPtr)
In your second example, with declaring let p12KeyFileContent = NSData(data: base64p12), the type of p12KeyFileContent is NSData, not NSData?. So, you cannot use ! for p12KeyFileContent.
Try changing the line as:
SecPKCS12Import(p12KeyFileContent, options, citemsPtr)
(! removed.)
One more.
You usually have no need to use withUnsafeMutablePointer to call SecPKCS12Import.
Try replacing these 3 lines (in your second example):
let resultPKCS12Import = withUnsafeMutablePointer(&citems) { citemsPtr in // line with the error
SecPKCS12Import(p12KeyFileContent!, options, citemsPtr)
}
with this:
let resultPKCS12Import = SecPKCS12Import(p12KeyFileContent, options, &citems)
The first example code can be rewritten as well.