繁体   English   中英

iOS 应用程序在发布模式下崩溃但在调试中不崩溃(使用 MongoDB 和 Stitch SDK)

[英]iOS App crashes in Release Mode but not in debug (using MongoDB and Stitch SDK)

我正在使用 MongoDB 和 Stitch SDK(StitchSDK 版本 6.4.0)。 我的 iPhone 应用程序在调试模式下运行,但当我将其构建为发行版并通过 TestFlight 安装时,它崩溃了。 我尝试更改构建设置中的优化级别,但没有成功。

设备日志中涉及崩溃线程的部分如下:

Thread 8 name:   Dispatch queue: com.apple.root.default-qos
Thread 8 Crashed:
0   bson                                   0x105f72748 bson_append_array + 120
1   MongoSwift                             0x105829db0 Array.encode(to:forKey:) + 1388
2   MongoSwift                             0x105829db0 Array.encode(to:forKey:) + 1388
3   MongoSwift                             0x10582c484 protocol witness for BSONValue.encode(to:forKey:) in conformance [A] + 24
4   MongoSwift                             0x10583ff50 specialized Document.init(dictionaryLiteral:) + 668
5   MongoSwift                             0x10583c6b8 Document.init(dictionaryLiteral:) + 24
6   StitchCoreSDK                          0x105d27788 CoreStitchServiceClientImpl.getCallServiceFunctionRequest(withName:withArgs:withTimeout:) + 220
7   StitchCoreSDK                          0x105d27db0 CoreStitchServiceClientImpl.callFunction<A>(withName:withArgs:withRequestTimeout:) + 120
8   StitchCoreSDK                          0x105d28414 protocol witness for CoreStitchServiceClient.callFunction<A>(withName:withArgs:withRequestTimeout:) in conformance CoreStitchServiceClientImpl + 16
9   StitchCoreRemoteMongoDBService         0x105bd06d0 CoreRemoteMongoReadOperation.executeRead() + 232
10  StitchCoreRemoteMongoDBService         0x105bd05cc CoreRemoteMongoReadOperation.toArray() + 12
11  StitchRemoteMongoDBService             0x105e8598c partial apply for closure #1 in RemoteMongoReadOperation.toArray(_:) + 28
12  StitchRemoteMongoDBService             0x105e859b0 partial apply for thunk for @escaping @callee_guaranteed () -> (@owned [A], @error @owned Error) + 24
13  StitchCore                             0x105ae410c closure #1 in OperationDispatcher.run<A>(withCompletionHandler:_:) + 136
14  StitchCore                             0x105ae3e44 thunk for @escaping @callee_guaranteed () -> () + 20
15  libdispatch.dylib                      0x1844f91a4 _dispatch_call_block_and_release + 24
16  libdispatch.dylib                      0x1844fa1a8 _dispatch_client_callout + 16
17  libdispatch.dylib                      0x18449c1fc _dispatch_queue_override_invoke + 728
18  libdispatch.dylib                      0x1844a943c _dispatch_root_queue_drain + 340
19  libdispatch.dylib                      0x1844a9c38 _dispatch_worker_thread2 + 172
20  libsystem_pthread.dylib                0x1def1fe48 _pthread_wqthread + 224
21  libsystem_pthread.dylib                0x1def1f9f0 start_wqthread + 8

我希望有人能帮助我!

我做了一个解决方法,将所有内容作为文本 (json stringify) 发送到 function,然后在 function 中将其转换回 json。它并不完美,但它可以工作。 如果有人想这样做,这里有一些代码,我也升级到 realm,但原理保持不变:

        // the part in the IOS app 
        
        let app = App(id: "yourapp");
        
        app.login(credentials: Credentials.anonymous) {
            (result) in
            DispatchQueue.main.async{
                switch result{
                case .failure(let error):
                    print("login failed: \(error)")
                case .success(let user):
                    print("Login as \(user) succeeded !")

                    var arrayPlog = [Logj]();
                    //let encoder = BSONEncoder()  // does not work
                    
                    // logs
                    let jsonObjectLog: [String : Any] = [
                        "logs": self.parseLogs(&arrayPlog)
                    ]
                    let jsonData = try? JSONSerialization.data(withJSONObject: jsonObjectLog, options: [])
                    let jsonString = String(data: jsonData!, encoding: String.Encoding.utf8)
                    
                    // user
                    let jsonObjectUser: [String : Any] = [
                        "user": self.getUserInfo()
                    ]
                    let jsonDataUser = try? JSONSerialization.data(withJSONObject: jsonObjectUser, options: [])
                    let jsonStringUser = String(data: jsonDataUser!, encoding: String.Encoding.utf8)
  
                    // call realm function
                    user.functions.AddData([AnyBSON(jsonString!),AnyBSON(jsonStringUser!)]){ Adddata, error in
                        guard error == nil else {
                            print("error")
                            return
                        }
                        print ("function called")
                    }
                    
                    
                }
            }
        }
        
        
     // as a sample the getUserInfo function    
    func getUserInfo() -> [String : Any?]{
        let dictionary = Bundle.main.infoDictionary!
        let version = dictionary["CFBundleShortVersionString"] as! String
        let build = dictionary["CFBundleVersion"] as! String
        let firmwareBuild = SettingsManager.sharedInstance.get(.sensorFirmwareVersion)

        
        let jsonObject : [String : Any?] = [
            "user_code" : SettingsManager.sharedInstance.get(.deviceUUID) ?? "",
            "sensor_fw_version": firmwareBuild,
            "sensor_mac_address": SettingsManager.sharedInstance.get(.sensorMacAddress) ?? ""
        ]
      
        return jsonObject
    }

    
// the AddData function in mongoDB  
    
exports = async function(log,user){
  /*
    Accessing application's values:
    var x = context.values.get("value_name");

    Accessing a mongodb service:
    var collection = context.services.get("mongodb-atlas").db("dbname").collection("coll_name");
    var doc = collection.findOne({owner_id: context.user.id});

    To call other named functions:
    var result = context.functions.execute("function_name", arg1, arg2);

    Try running in the console below.
  */
 
  console.log(" begin of function  ")
  var success = 1;  // do not use a boolean because maybe clients do not support it

  try {
    
    
    // USERS PART
    const atlas = context.services.get('mongodb-atlas');
    var retVal = "empty";
    var res = null;
    var users = atlas.db("yourDB").collection("users");
    
    if (Array.isArray(user)) // needed for IOS
    {
       user = user[0];
       
    }
    

    console.log(typeof user);
    console.log(typeof log)
    console.log("before parse user:" + user)
    console.log("before parse log:" + log)
    
    if (typeof user == "string") // to fix the ios BSON bug..
    {
      const objUser = JSON.parse(user);
      const objLog = JSON.parse(log);

      user = objUser.user
      log = objLog.logs
    }
    
    res =  await atlas.db('yourDB').collection('users').find({  user_code:  user.user_code}).limit(10).toArray();

    console.log(res)
    if (res.length > 1)
    {
      res[0] = res[res.length-1]; // see if we can remove this replace one will probably replace the first one anyway 
      //errorstr = "user has more then 1 user entrys, using the last one"
    }
    var updated_at = Date();
    var created_at = null;
    
    if (res.length==0)
    {
      created_at = Date();
    }
    else
    {
      created_at = res[0].created_at;
    }
  
    user.created_at = created_at;
    user.update_at = updated_at;
    
    var createdUserData = await users.replaceOne({user_code: user.user_code},user,{upsert: true}); // replace if already existed else create new one
 
    console.log("created User: " + createdUserData)   
    // createdUserData does not return the created data so ask for it because we need the id of the record.
    // upsertedId should be available according documentation but I could not make it work
    // res[0] should always exist by now
    res =  await atlas.db('yourDB').collection('users').find({  user_code:  user.user_code}).limit(1).toArray(); // just ask the latest 
    console.log("res :" + res)
    
    //  LOGS PART
    created_at = Date();  // created data is always new for the _logs there are no updates of a record only new ones
    var logs =  await atlas.db('yourDB').collection('_logs')
    // so logs are the complete logs in the DB, log is the current entry that needs to be put in the DB
    if (Array.isArray(log))
    {
       console.log("array of log")
       var i = 0;
       for (i=0; i< log.length ; i++)
       {
          log[i].user_id = res[0]._id; 
          log[i].creation_at = created_at;
          log[i].update_at = updated_at;
          await logs.insertOne(log[i]);
       }
    }
    else
    {
      console.log("single log")
      log.user_id = res[0]._id;  // link user_id of this log with the _id of the user in the users-collection
      console.log("log extended with user_id :" + log)
      log.creation_at = created_at;
      log.update_at = updated_at;
      console.log("before insertone :" + log)
      await logs.insertOne(log);
    }
    console.log(" voor logs find")
    res = await logs.find({ user_id: res[0]._id }).limit(100).toArray();
    console.log(" na logs find")
    if (Array.isArray(res))
      retVal = res;
  }catch(error)
  {
    console.log("error in function")
    success = 0;
  }
   
  return success;
}
            

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM