[英]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.