techgirl08 techgirl08 - 2 months ago 19
iOS Question

Could not cast value of type 'Swift.Array<Swift.String>' (0x61000028bb50) to 'Swift.String' (0x10cbd0ae0)

I have a program that does an initial search of users then populates a table. There are two buttons within the table to accept the users request and another to deny, these buttons call an insert function that inputs the results in the database. The array results are being passed to the function but I'm getting an error of 'Could not cast value of type 'Swift.Array' (0x61000028bb50) to 'Swift.String' (0x10cbd0ae0)' on the following line of code:

self.insertShot("No", (gname as? String as AnyObject))


The gname variable is declared as follows:

var gname = String

Here is the code that is getting the array data:

for i in 0 ..< self.guest.count {

let ava = self.guest[i]["ava"] as? String

let gname = self.guest[i]["username"] as? String
let city = self.guest[i]["city"] as? String
let state = self.guest[i]["state"] as? String
let url = NSURL(string: ava!)!
self.avas.append(image)
self.gname.append((gname as AnyObject) as! String)
self.tableView.reloadData()


InsertShot function

public func insertShot(_ rating : String,_ gname : AnyObject) {
// shortcuts to data to be passed to php file

let reviewer = user?["username"] as! String
print("print 3", gname)

// url path to php file
let url = URL(string: "http://www.xxxxx.com/xxxxx.php")!
var request = URLRequest(url: url)
request.httpMethod = "POST"

// param to be passed to php file
let param = [
"user" : reviewer,
"revieweduser" : gname,
"rating" : rating
] as [String : Any]

// body
let boundary = "Boundary-\(UUID().uuidString)"
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

// ... body
request.httpBody = createBodyWithParams(param as? [String : String], boundary: boundary)


// launch session
URLSession.shared.dataTask(with: request) { data, response, error in

// get main queu to communicate back to user
DispatchQueue.main.async(execute: {


if error == nil {

do {

// json containes $returnArray from php
let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

// declare new var to store json inf
guard let parseJSON = json else {
print("Error while parsing")
return
}

// get message from $returnArray["message"]
let message = parseJSON["users"]
//print(message)

// if there is some message - post is made
if message != nil {

// reset UI
// self.msgTxt.text = ""

// switch to another scene
//self.tabBarController?.selectedIndex = 3
_ = self.navigationController?.popViewController(animated: true)


}

} catch {

// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = "\(error)"
appDelegate.infoView(message: message, color: colorSmoothRed)
})
return

}

} else {

// get main queue to communicate back to user
DispatchQueue.main.async(execute: {
let message = error!.localizedDescription
appDelegate.infoView(message: message, color: colorSmoothRed)
})
return

}


})

}.resume()
return

}


The following functions are used when the Yes or No buttons are selected and they call the InsertShots function:

@IBAction func noBtn_clicked(_ sender: UIButton) {
print("print 6", gname)
self.insertShot("No", (gname as? String as AnyObject))
//doSearch("")

}
@IBAction func yesBtn_clicked(_ sender: UIButton, users: AnyObject) {

self.insertShot("Yes", (gname as? String as AnyObject))

}

Answer Source

It seems you may be inadvertently passing the array self.gname instead of a simple String. From the context I have, I can't tell if you're trying to pass in an array or a string. Your code is making much too much use of the "no type" types, such as Any and AnyObject. You are explicitly disabling the safety and the helpfulness of the Swift type system.

I'd recommend changing your function declaration to indicate exactly what you need. Such as:

public func insertShot(_ rating: String, _ gname: String)

then within the body, you can change your dictionary declaration to

let param = [
    "user" : reviewer,
    "revieweduser" : gname,
    "rating" : rating
]

Then drop the cast:

request.httpBody = createBodyWithParams(param, boundary: boundary)

You are passing in self.gname which is an Array of Strings. You need to pass in a String.

Change you could to this: if let gnameString = self.gname.first { self.insertShot("Yes", gnameString) }

Note: Your code is creating an array, you presumably need to figure out which value in the array you want to pass in.