【问题标题】:iOS App crashes in Release Mode but not in debug (using MongoDB and Stitch SDK)iOS 应用程序在发布模式下崩溃但在调试中不崩溃(使用 MongoDB 和 Stitch SDK)
【发布时间】:2022-02-24 22:35:43
【问题描述】:

我正在使用 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

希望有人能帮帮我!

【问题讨论】:

  • 一年前我也遇到过同样的问题,可惜没有时间解决。似乎问题仍然存在......
  • 似乎是一个已知问题(我认为它是一样的?)但他们不会修复它,因为您必须通过同步升级到 REALM 应用程序...github.com/mongodb/stitch-ios-sdk/issues/206

标签: swift crash release mongodb-stitch


【解决方案1】:

我做了一个解决方法,将所有内容作为文本(json stringify)发送到函数,然后在函数中将其转换回 json。它并不完美,但它确实有效。这是一些代码,如果有人想做同样的事情,我也升级到领域,但原理保持不变:

        // 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;
}
            

【讨论】:

    猜你喜欢
    • 2012-08-20
    • 1970-01-01
    • 2018-03-22
    • 2019-09-11
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多