Math

MyScript MathWidget unserialize crashes on physical device while working fine on the simulator.

I am using Mathwidget for retrieving data from a file to MathWidget.   
The code crashes while calling MathWidget.unserialize(NSData).


Dear Yasir,


Would it be possible for you to give us more details so we can try to reproduce the issue?


Best regards

image



Kindly update us on this issue or what more details would you want from us?

In order to facilitate our testing, we would appreciate to know:

- XCode version

- iOS device model and ios version

- does the crash occur with the default sample or with an app integrating the widget?


Best regards


Please find below the details,

XCode version used = Version 8.0 (8A218a)

iOS device model =  MGLW2J/A and ios version = vs. 10.3.3(14G60)

crash occurred in our app integrating the widget.


Regards.

crash also observed on same device model with ios version = Version: 9.3.5 (13G36) , release made from same xcode version.

This is happening always whenever we try to unserialize the data. 

Thanks for those details, could you please try to reproduce the issue using the default sample after dding your code to call the unserialize function. It will help us troubleshooting this issue.

Best regards

image


Ok, I tried this in default sample and still find same issue this same code is working fine on simulator but on device it still crashes on unserialize call , i have passed the same data bytes i got after mathwidgets serialize call and passed it to unserialize and it works in simulator but crashes on device. Kindly look into this issue.


Thanks & Regards,

Syed Waheed ul Haq

Thanks again for your testing and feedback. I have discussed with our developer team, and we would be interested to do more tests on our side. To so, could you please add below your code regarding serialize and unserialize functions? 

We wonder if the problem could be due to permissions that are not managed the same way on device compared to the simulator? Where do you store your data to unserialize?


Thanks for your patience.

@IBAction func btnOkEE(_ sender: AnyObject) {

        //Check if widget is nil

        if(self.mathWidget.mathView.resultAsText() != nil && self.mathWidget.mathView.resultAsText() != ""){

            var eeControlsData :NSMutableDictionary = NSMutableDictionary()

            let persistData = UserDefaults.standard

            //Update session if it is not in read only mode

            if(!self.isReadOnly){

                //Get all the data of equation editor

                let eeData:NSMutableDictionary = getEEData()

                var EEControlData : NSMutableDictionary = eeData.object(forKey: "ee") as! NSMutableDictionary

                var value = ""

                let filename = EEControlData.object(forKey: "bytesdataPath")

                let serializeResult:Data = eeRestore(filePath: filename as! String)

                if serializeResult.count > 0 {

                    self.mathWidget.mathView.unserialize(serializeResult)

                }

 

                var jsonString:String = ""

                if persistData.object(forKey: "EEValue") != nil {

                    eeControlsData = persistData.object(forKey: "EEValue") as! NSMutableDictionary

                    let jsonData: NSData

                    do

                    {

                        jsonData = try JSONSerialization.data(withJSONObject: eeData, options: JSONSerialization.WritingOptions()) as NSData

                        jsonString = NSString(data: jsonData as Data, encoding: String.Encoding.utf8.rawValue) as! String

                    }

                    catch _{

                    }

                    if eeControlsData.object(forKey: self.eeId) != nil

                    {

                        eeControlsData.removeObject(forKey: self.eeId)

                        eeControlsData.setValue(jsonString, forKey: self.eeId)

                    }

                    else{

                        eeControlsData.setValue(jsonString, forKey: self.eeId)

                    }

                }

                else

                {

                    eeControlsData.setValue(jsonString, forKey: self.eeId)

                }

                //Save Equation Editor Control Data in session

                persistData.setValue(eeControlsData, forKey: "EEValue")

                persistData.synchronize()

            }

        }

        else{

            return

        }

        self.willMove(toParentViewController: nil)

        self.view.removeFromSuperview()

        self.removeFromParentViewController()

    }


func getEEData() -> NSMutableDictionary{

        self.eeId = "EquationEditor1"

        var eeJsonObject:NSMutableDictionary = NSMutableDictionary()

        eeJsonObject.setValue(self.eeId, forKey: "eeid")

        //Check if value is not null

        if let eeImage:UIImage = self.mathWidget.mathView.resultAsImage(){

            let eeImageData:NSData = UIImagePNGRepresentation(eeImage)! as NSData

            if eeImageData != nil {

                let strBase64 = eeImageData.base64EncodedString(options:[])

                eeJsonObject.setValue(strBase64, forKey: "thumbnail")

            }

            else{

                eeJsonObject.setValue("", forKey: "thumbnail")

            }

 

        }

        else{

            eeJsonObject.setValue("", forKey: "thumbnail")

        }

        eeJsonObject.setValue(self.mathWidget.mathView.resultAsText(), forKey: "equationvalue")

        //Setting file path

        serializeResult = self.mathWidget.mathView.serialize()

        let path:String = eePathSave(serializeResult: serializeResult,filename: (UUID().uuidString + ".test"))

        eeJsonObject.setValue(path, forKey: "bytesdataPath")

        var controlObject:NSMutableDictionary = NSMutableDictionary()

        controlObject.setValue(eeJsonObject, forKey: "ee")

        return controlObject

    }



structure of EEControlData dictionary after function getEEData() was called is as shown in below snapshot ,

image

This also shows that we are saving our serialize result at following location and fetching it from there too, 

/var/mobile/Containers/Data/Application/2EF3912A-1827-4614-8FE1-431493C9C0F8/Documents/3783FB89-8C11-4FD3-8D3B-8CEA9A492C60.test

  


Please note that btnOkEE event is raised when we type something in mathwidget and press Ok button we added there inside which it first calls getEEData() where it serializes it and saves this file at following location

/var/mobile/Containers/Data/Application/2EF3912A-1827-4614-8FE1-431493C9C0F8/Documents/3783FB89-8C11-4FD3-8D3B-8CEA9A492C60.test


and after which we added our unserialize code right after this where it reads bytes from that file and tries to unserialize it and crashes on device. Do note that the file is there and we are getting the bytes from below in serializeResult, it crashes in unserialize right after it.

let serializeResult:Data = eeRestore(filePath: filename as! String) 

 if serializeResult.count > 0 {

                    self.mathWidget.mathView.unserialize(serializeResult)

                }


also pasting eeRestore() function,


func eeRestore(filePath:String) -> Data{

        var eeData:Data = Data()

        let fileManager = FileManager.default

        print(filePath)

        if fileManager.fileExists(atPath: filePath) {

            eeData = fileManager.contents(atPath: filePath)!

        }

        return eeData

    }


Thanks for those details. We have checked with the developers and don't see what could cause a crash on device whereas it does not occur in the simulator at first sight. It would be easier if you could share your project so we can have a look and try to find what's wrong with your code. As the method is quite long, the 'bad access' crash can occur at very different steps. again it will be easier to debug directly with your project.

Thanks for your patience!

Please find below shareable link to the default sample project discussed above in which this issue can be observed.

https://drive.google.com/open?id=0B_zWtLHJ4JbxQ3NmNXhzT2N4VkU

After extracting , inside MyScript_ATK folder go in samples inside it go in MathWidgetSample and load its xcodeproj file in xcode , run the project on device and type something in mathwidget then press Ok button to see the crash.


Thanks, we don't reproduce this crash on XCode latest version, however it seems there is some problem with this part of the code:

"eeControlsData.removeObject(forKey: self.eeId)"


... MathWidgetSample[24116:10430425] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary removeObjectForKey:]: mutating method sent to immutable object'


We also tried to unserialize manually corrupted data, but in this case we don't get the same error as yours:

"libc++abi.dylib: terminating with uncaught exception of type myscript::engine::EngineError: IO_FAILURE"


Unfortunately we have no other idea to troubleshoot, as we don't reproduce the problem on our side, sorry.


Best regards

Login or Signup to post a comment
  • Support
  • Forums
  • Math
  • MyScript MathWidget unserialize crashes on physical device while working fine on the simulator.