0

When the iOS app trigger an API event named "addtocart" the app crashes returning below error.

url https://example.com/index.php/?route=api/cart/addToCart params ["product_id": "12098", "option": "{\n\n}", "quantity": "0", "token": "2f42lqjie21cbzr1r0gsgphqtl", "width": "750.000000"] { error = 1; message = ( "Color required!" ); } Could not cast value of type '__NSSingleObjectArrayI' (0x1b5bee3b0) to 'NSString' (0x1b5bfaad8). 2018-08-02 19:50:28.493678+0300 Ishtari[35479:3846514] Could not cast value of type '__NSSingleObjectArrayI' (0x1b5bee3b0) to 'NSString' (0x1b5bfaad8). warning: could not execute support code to read Objective-C class data in the process. This may reduce the quality of type information available. (lldb)

The product has option called color so before adding to cart the user should choose the color of the item to checkout. The app is return the option name "Color" but not giving me the values to pick from ("option": "{\n\n}") which causing the app to crash giving above error when callingHTTPApi.

   func callingHttppApi(){
        DispatchQueue.main.async{
            NetworkManager.sharedInstance.showLoader()
            let sessionId = self.defaults.object(forKey:"ic_token");
            let width = String(format:"%f", SCREEN_WIDTH * UIScreen.main.scale)
            self.view.isUserInteractionEnabled = false

            if self.whichApiToProcess == "addtocart"{
                var requstParams = [String:String]();
                requstParams["width"] = width
                requstParams["product_id"] = self.productId
                requstParams["ic_token"] = sessionId as? String
                requstParams["quantity"] = self.quantityValue.text
                do {
                    let jsonSortData =  try JSONSerialization.data(withJSONObject: self.optionDictionary, options: .prettyPrinted)
                    let jsonSortString:String = NSString(data: jsonSortData, encoding: String.Encoding.utf8.rawValue)! as String
                    requstParams["option"] = jsonSortString
                }
                catch {
                    print(error.localizedDescription)
                }


                NetworkManager.sharedInstance.callingHttpRequest(params:requstParams, apiname:"cart/addToCart", cuurentView: self){success,responseObject in
                    if success == 1{
                        let dict = responseObject as! NSDictionary;
                        NetworkManager.sharedInstance.dismissLoader()
                        if dict.object(forKey: "fault") != nil{
                            let fault = dict.object(forKey: "fault") as! Bool;
                            if fault == true{
                                self.loginRequest()
                            }
                        }else{
                            print(dict)
                            self.view.isUserInteractionEnabled = true
                            let dict = responseObject as! NSDictionary
                            if dict.object(forKey: "error") as! Int == 0{
                                NetworkManager.sharedInstance.showSuccessSnackBar(msg: dict.object(forKey: "message") as! String)
                                let data = dict.object(forKey: "total") as! String
                                self.tabBarController!.tabBar.items?[3].badgeValue = data.components(separatedBy: " ")[0]
                                self.navigationCart(cartCount:data.components(separatedBy: " ")[0])
                                if self.goToBagFlag == true{
                                    self.tabBarController!.selectedIndex = 3
                                }

                            }else{
                                NetworkManager.sharedInstance.showWarningSnackBar(msg: dict.object(forKey: "message") as! String)
                            }
                        }
                    }else if success == 2{
                        NetworkManager.sharedInstance.dismissLoader()
                        self.callingHttppApi()
                    }
                }
            }

When it crashes the console directs me to this line

                        }else{
                            NetworkManager.sharedInstance.showWarningSnackBar(msg: dict.object(forKey: "message") as! String)
                        }

Any help please!

David Buik
  • 522
  • 1
  • 8
  • 31

1 Answers1

0

The error is clear:

Could not cast value of type '__NSSingleObjectArrayI' (0x1b5bee3b0) to 'NSString' (0x1b5bfaad8)

The left side shows the actual type (Array), the right side is what you are doing wrong (String)

NetworkManager.sharedInstance.showWarningSnackBar(msg: dict.object(forKey: "message") as! [String])

If msg is supposed to be String join the strings

let messageArray = dict.object(forKey: "message") as! [String] 
NetworkManager.sharedInstance.showWarningSnackBar(msg: messageArray.joined(separator: ", "))

By the way use Swift native types and key subscription

let dict = responseObject as! [String:Any]
...
NetworkManager.sharedInstance.showWarningSnackBar(msg: dict["message"] as! [String])

And – sorry – this syntax is horrible:

let jsonSortString:String = NSString(data: jsonSortData, encoding: String.Encoding.utf8.rawValue)! as String

Please replace it with

let jsonSortString = String(data: jsonSortData, encoding: .utf8)!
vadian
  • 274,689
  • 30
  • 353
  • 361
  • Thank you saved my day. Yet one thing if this is related to same question otherwise I'll post a new one. The options aren't populating in the app, I can see the option type but not the items related. – David Buik Aug 02 '18 at 19:15
  • `optionDictionary` is obviously empty. And please don't `prettyPrint` the json. The server doesn't care about prettiness. – vadian Aug 02 '18 at 19:22
  • Thanks again, you're referring to his `var optionDictionary = [String:AnyObject]()` I'm gonna check if the empty response coming from the API or the app can't retrieve it well. And for the `prettyPrint` so you advice to stop it? – David Buik Aug 02 '18 at 21:41
  • I'm not sure if that's allowed but I posted a new question about retrieve a property value from NSArray child-array over here [https://stackoverflow.com/questions/51662511/swift-retrieve-a-property-value-from-child-array-object] – David Buik Aug 02 '18 at 21:42
  • Yes, `.prettyPrinted` is for humans and creates extra whitespace characters. And don't use `NS(Mutable` collection types in Swift at all. You throw away the strong type information. – vadian Aug 03 '18 at 04:01