ios Realm 对象已被删除或失效
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/31852782/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Realm object has been deleted or invalidated
提问by Padarom
When I start my app, I perform an API call to see whether there's new data available. The data is stored in my local Realm database, and some of it is displayed in the initial table view controller.
当我启动我的应用程序时,我会执行一个 API 调用来查看是否有新数据可用。数据存储在我本地的 Realm 数据库中,其中一些显示在初始表视图控制器中。
Once the API call is finished, I check if some conditions are met that require me to delete a bunch of the previous data from the database and then create new objects. However, when I delete the old data, my app crashes with the following exception:
API调用完成后,我检查是否满足某些条件,要求我从数据库中删除一堆以前的数据,然后创建新对象。但是,当我删除旧数据时,我的应用程序崩溃并出现以下异常:
2015-08-06 11:56:32.057 MSUapp[19754:172864] *** Terminating app due to uncaught exception 'RLMException', reason: 'Object has been deleted or invalidated.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010660cc65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x00000001083bdbb7 objc_exception_throw + 45
2 Realm 0x0000000105b78e95 _ZL17RLMVerifyAttachedP13RLMObjectBase + 85
3 Realm 0x0000000105b7878d _ZL10RLMGetLinkP13RLMObjectBasemP8NSString + 29
4 Realm 0x0000000105b7c23e ___ZL17RLMAccessorGetterP11RLMProperty15RLMAccessorCodeP8NSString_block_invoke_12 + 46
5 MSUapp 0x0000000105764867 _TFFC6MSUapp29FavoriteLeaguesViewController18generateLeagueListFS0_FT_T_U_FTCS_6LeagueS1__Sb + 39
6 MSUapp 0x00000001057648eb _TTRXFo_oC6MSUapp6LeagueoS0__dSb_XFo_iS0_iS0__dSb_ + 27
7 libswiftCore.dylib 0x0000000108674ae2 _TFSs14_insertionSortUSs21MutableCollectionType_USs13GeneratorType__Ss22BidirectionalIndexType_Ss18_SignedIntegerType_Ss33_BuiltinIntegerLiteralConvertible____FTRQ_GVSs5RangeQQ_5Index_RFTQQQ_9Generator7ElementS7__Sb_T_ + 1570
8 libswiftCore.dylib 0x0000000108676682 _TFSs14_introSortImplUSs21MutableCollectionType_USs13GeneratorType__Ss21RandomAccessIndexType_Ss18_SignedIntegerType_Ss33_BuiltinIntegerLiteralConvertible_Ss16SignedNumberType_S3_____FTRQ_GVSs5RangeQQ_5Index_RFTQQQ_9Generator7ElementS8__SbSi_T_ + 1250
9 libswiftCore.dylib 0x0000000108676172 _TFSs10_introSortUSs21MutableCollectionType_USs13GeneratorType__Ss21RandomAccessIndexType_Ss18_SignedIntegerType_Ss33_BuiltinIntegerLiteralConvertible_Ss16SignedNumberType_S3_____FTRQ_GVSs5RangeQQ_5Index_FTQQQ_9Generator7ElementS8__Sb_T_ + 1058
10 libswiftCore.dylib 0x00000001085ec947 _TFSs4sortUSs21MutableCollectionType_USs13GeneratorType__Ss21RandomAccessIndexType_Ss18_SignedIntegerType_Ss33_BuiltinIntegerLiteralConvertible_Ss16SignedNumberType_S3_____FTRQ_FTQQQ_9Generator7ElementS6__Sb_T_ + 471
11 libswiftCore.dylib 0x00000001086a8d9e _TPA__TFFSa4sortU__FRGSaQ__FFTQ_Q__SbT_U_FRGVSs26UnsafeMutableBufferPointerQ__T_ + 222
12 libswiftCore.dylib 0x00000001086a8e18 _TPA__TTRG0_R_XFo_lGVSs26UnsafeMutableBufferPointerq___dT__XFo_lGS_q___iT__42 + 56
13 libswiftCore.dylib 0x00000001085f7fda _TFSa30withUnsafeMutableBufferPointerU__fRGSaQ__U__FFRGVSs26UnsafeMutableBufferPointerQd___Q_Q_ + 522
14 libswiftCore.dylib 0x00000001085f7db4 _TFSa4sortU__fRGSaQ__FFTQ_Q__SbT_ + 132
15 MSUapp 0x0000000105761709 _TFC6MSUapp29FavoriteLeaguesViewController18generateLeagueListfS0_FT_T_ + 1097
16 MSUapp 0x000000010576354b _TFC6MSUapp29FavoriteLeaguesViewController27numberOfSectionsInTableViewfS0_FCSo11UITableViewSi + 59
17 MSUapp 0x00000001057635fa _TToFC6MSUapp29FavoriteLeaguesViewController27numberOfSectionsInTableViewfS0_FCSo11UITableViewSi + 58
18 UIKit 0x000000010737cac3 -[UITableViewRowData _updateNumSections] + 84
19 UIKit 0x000000010737d4b4 -[UITableViewRowData invalidateAllSections] + 69
20 UIKit 0x00000001071c873b -[UITableView _updateRowData] + 217
21 UIKit 0x00000001071de2b7 -[UITableView noteNumberOfRowsChanged] + 112
22 UIKit 0x00000001071dd9f5 -[UITableView reloadData] + 1355
23 MSUapp 0x00000001057647c6 _TFFC6MSUapp29FavoriteLeaguesViewController11viewDidLoadFS0_FT_T_U_FTO10RealmSwift12NotificationCS1_5Realm_T_ + 166
24 RealmSwift 0x0000000105f37210 _TFF10RealmSwift41rlmNotificationBlockFromNotificationBlockFFT12notificationOS_12Notification5realmCS_5Realm_T_bTSSCSo8RLMRealm_T_U_FTSSS2__T_ + 224
25 RealmSwift 0x0000000105f372af _TTRXFo_oSSoCSo8RLMRealm_dT__XFdCb_dCSo8NSStringdS__dT__ + 111
26 Realm 0x0000000105c0645a -[RLMRealm sendNotifications:] + 986
27 Realm 0x0000000105c068e6 -[RLMRealm commitWriteTransaction] + 262
28 Realm 0x0000000105c06a48 -[RLMRealm transactionWithBlock:] + 120
29 RealmSwift 0x0000000105f34250 _TFC10RealmSwift5Realm5writefS0_FFT_T_T_ + 176
30 MSUapp 0x00000001056d46db _TZFC6MSUapp14DatabaseHelper23removeForSportAndSeasonfMS0_FTCS_5Sport6seasonSS_T_ + 603
31 MSUapp 0x0000000105710d22 _TFFFC6MSUapp11AppDelegate14loadRemoteDataFS0_FT_T_U_FGSaCS_5Sport_T_U_FGSaCS_6League_T_ + 866
32 MSUapp 0x0000000105710dc7 _TTRXFo_oGSaC6MSUapp6League__dT__XFo_iGSaS0___iT__ + 23
33 MSUapp 0x00000001057103d1 _TPA__TTRXFo_oGSaC6MSUapp6League__dT__XFo_iGSaS0___iT__ + 81
34 MSUapp 0x000000010575de90 _TTRXFo_iGSaC6MSUapp6League__iT__XFo_oGSaS0___dT__ + 32
35 MSUapp 0x000000010575ddeb _TFZFC6MSUapp9APIHelper11loadLeaguesFMS0_FTSi18shouldWriteToRealmSb10completionGSqFGSaCS_6League_T___T_U_FCSo6NSDataT_ + 2763
36 MSUapp 0x00000001056f4a0e _TTSf2n_n_n_n_n_d_i_n_n_n___TFFC6MSUapp14JSONDataSource18loadRemoteJsonDataFS0_FTSSCS_19GETParameterBuilderFCSo6NSDataT__T_U_FTCSo12NSURLRequestGSqCSo17NSHTTPURLResponse_GSqS2__GSqCSo7NSError__T_ + 2302
37 MSUapp 0x00000001056f2d59 _TPA__TTSf2n_n_n_n_n_d_i_n_n_n___TFFC6MSUapp14JSONDataSource18loadRemoteJsonDataFS0_FTSSCS_19GETParameterBuilderFCSo6NSDataT__T_U_FTCSo12NSURLRequestGSqCSo17NSHTTPURLResponse_GSqS2__GSqCSo7NSError__T_ + 249
38 Alamofire 0x00000001059e7599 _TTRXFo_oCSo12NSURLRequestoGSqCSo17NSHTTPURLResponse_oGSqCSo6NSData_oGSqCSo7NSError__dT__XFo_oS_oGSqS0__iGSqS1__oGSqS2___dT__ + 25
39 Alamofire 0x00000001059e7461 _TFFFC9Alamofire7Request8responseFDS0_US_18ResponseSerializer___FT5queueGSqCSo8NSObject_18responseSerializerQ_17completionHandlerFTCSo12NSURLRequestGSqCSo17NSHTTPURLResponse_GSqQ0__GSqCSo7NSError__T__DS0_U_FT_T_U_FT_T_ + 737
40 Alamofire 0x00000001059e690e _TPA__TFFFC9Alamofire7Request8responseFDS0_US_18ResponseSerializer___FT5queueGSqCSo8NSObject_18responseSerializerQ_17completionHandlerFTCSo12NSURLRequestGSqCSo17NSHTTPURLResponse_GSqQ0__GSqCSo7NSError__T__DS0_U_FT_T_U_FT_T_ + 206
41 Alamofire 0x00000001059a89d7 _TTRXFo__dT__XFdCb__dT__ + 39
42 libdispatch.dylib 0x000000010938b186 _dispatch_call_block_and_release + 12
43 libdispatch.dylib 0x00000001093aa614 _dispatch_client_callout + 8
44 libdispatch.dylib 0x0000000109392a1c _dispatch_main_queue_callback_4CF + 1664
45 CoreFoundation 0x00000001065741f9 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
46 CoreFoundation 0x0000000106535dcb __CFRunLoopRun + 2043
47 CoreFoundation 0x0000000106535366 CFRunLoopRunSpecific + 470
48 GraphicsServices 0x000000010cc17a3e GSEventRunModal + 161
49 UIKit 0x00000001070f08c0 UIApplicationMain + 1282
50 MSUapp 0x000000010570f857 main + 135
51 libdyld.dylib 0x00000001093df145 start + 1
52 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
This call stack lets me assume, that it's because of my write access in FavoriteLeaguesViewController's generateLeagueList
method. The following is its body:
这个调用堆栈让我假设,这是因为我在FavoriteLeaguesViewController 的generateLeagueList
方法中的写访问权限。下面是它的主体:
var favorites = FavoritesHelper.sharedInstance.favoriteLeagues
favorites.sort { var favoriteLeagues: [League] {
get {
var leagues = [League]()
for id in favoriteLeagueIDs {
if let league = realm.objectForPrimaryKey(League.self, key: id) {
leagues.append(league)
}
}
return leagues
}
}
.sport < .sport }
for favorite in favorites {
// Add to array, which we can later use for cellForRowAtIndexPath
}
favorites
is of the type [League]
, where League
is a Realm Object. I'd assume the exception occurs because I'm accessing properties of the League
objects, which have been deleted from the Realm database in the mean time (because the API call that has been started in the AppDelegate is now finished).
favorites
是 类型[League]
,其中League
是领域对象。我假设发生异常是因为我正在访问同时League
从 Realm 数据库中删除的对象的属性(因为在 AppDelegate 中启动的 API 调用现在已经完成)。
My question then is: How can I prevent this from happening? How can I make sure that there's no more writing/reading-access to any of the League
objects prior to deleting them?
那么我的问题是:我怎样才能防止这种情况发生?League
在删除任何对象之前,我如何确保没有更多的写入/读取访问权限?
采纳答案by Padarom
The issue was in my FavoritesHelper
class. It had both a favoriteLeagueIDs
and favoriteLeagues
property. I always set both of them and used the IDs for internal usage and the other property for whenever I want some data from these leagues.
问题出在我的FavoritesHelper
班级。它同时具有 afavoriteLeagueIDs
和favoriteLeagues
property。我总是设置它们,并将 ID 用于内部使用,而其他属性则用于我想要这些联赛的一些数据时。
This meant, that all favorite leagues were constantly referenced by the favoriteLeagues
property (of the type [League]
), thus crashing the app when I wanted to fetch them after they're invalidated.
这意味着,所有最喜欢的联赛都被favoriteLeagues
属性(类型为[League]
)不断引用,因此当我想在它们失效后获取它们时,应用程序会崩溃。
What I've done to fix this, was to change the property favoriteLeagues
to a computed property as follows:
我为解决这个问题所做的是将属性更改favoriteLeagues
为计算属性,如下所示:
// Realm/RLMUtil.mm:266
static NSException *RLMException(NSString *reason, NSDictionary *additionalUserInfo) {
// add some code to generate a swift error. E.g. division-by-zero.
int a = 0;
if (reason == nil) {
a = 1;
}
NSLog(@"calculating 1 / %d = %f", a, 1 / a);
... remainder of the original code...
}
Now the leagues are no longer referenced and just get loaded from the database when I need to read them. Invalidated or deleted objects don't get loaded because of the if let
statement (the Realm.objectForPrimaryKey(:key:)
method returns nil
in such a case).
现在,联赛不再被引用,只是在我需要阅读它们时从数据库中加载。由于该if let
语句(在这种情况下该Realm.objectForPrimaryKey(:key:)
方法返回)nil
,不会加载无效或删除的对象。
回答by segiddins
You can check if an object has been deleted from the Realm by calling object.invalidated
-- if it returns true
, then it has been deleted or the Realm has manually invalidated.
您可以通过调用来检查对象是否已从 Realm 中删除object.invalidated
-- 如果它返回true
,则它已被删除或 Realm 已手动失效。
回答by wjiee weofej
I got a really nice way to catch a RLMException within Swift.
我有一个非常好的方法来在 Swift 中捕获 RLMException。
Currently Swift doesn't show where a RLMException happened.
目前 Swift 没有显示 RLMException 发生的位置。
In Realm/RLMUtil.mm:266, there is the definition for RLMException.
在 Realm/RLMUtil.mm:266 中,有 RLMException 的定义。
If you change the code to generate a swift error,
如果您更改代码以生成快速错误,
Xcode now can show you where the exception occurred.
Xcode 现在可以显示异常发生的位置。
Now it is a part of Swift.
现在它是 Swift 的一部分。
// Realm/RLMUtil.mm:193
static NSException *RLMException(NSString *reason, NSDictionary *additionalUserInfo) {
// ...
}
回答by NazarYavornytskyy
I've just place breakpoint inside method:
我刚刚在方法中放置了断点:
try! realm.write {
realm.add(...)
}
And on left panel you can check stack trace, here you can find where error throws.
在左侧面板上,您可以检查堆栈跟踪,在这里您可以找到错误抛出的位置。
回答by Fabio Ciurlia
Try to createthe element on realm instead of add
尝试在领域上创建元素而不是添加
So:
所以:
try! realm.write {
realm.create(...)
}
Replace with:
用。。。来代替:
/**
Indicates if the object can no longer be accessed because it is now invalid.
An object can no longer be accessed if the object has been deleted from the Realm that manages it, or
if `invalidate` is called on that Realm.
*/
@property (nonatomic, readonly, getter = isInvalidated) BOOL invalidated;
And then after the delete operation realm should work as expected!
然后在删除操作后领域应该按预期工作!
回答by marcel
I was unable to place breakpoints within the Realm framework itself as others suggested, but instead placed an exception breakpoint on my entire project:
我无法像其他人建议的那样在 Realm 框架本身中放置断点,而是在我的整个项目中放置了一个异常断点:
This allowed me to catch a proper stack trace when the exception was thrown, and find my bug.
这使我能够在抛出异常时捕获正确的堆栈跟踪,并找到我的错误。
回答by Qun Li
you can calling isInvalidated
or invalidated
to judge the object is invalid (YES) or not (NO).
you can also write a a custom method to define what is real invalidate
您可以调用 isInvalidated
或invalidated
判断对象无效(YES)或无效(NO)。您还可以编写自定义方法来定义什么是真实的invalidate
look for the document ,we will see a property:
查找文档,我们将看到一个属性:
try! realm.write {
print("deleted word: \(targetObject.word)")
realm.delete(targetObject)
// targetObject was removed, so don't try to access it otherwise you gonna got the 'nil' value instead of object.
}
the invalidated
is readonly but what does isInvalidated
mean?
该invalidated
是只读的,但什么呢isInvalidated
是什么意思?
it is equals to - (BOOL)invalidated { return invalidated; }
它等于 - (BOOL)invalidated { return invalidated; }
it means that you can write a a custom method to define what is real invalidate
you want.
这意味着您可以编写自定义方法来定义invalidate
您想要的真实内容。
回答by asilturk
In my experience, if you trying to use target object (which you wanna delete) after delete, application will crash.
根据我的经验,如果您在删除后尝试使用目标对象(您要删除的对象),应用程序将崩溃。
If you wanna trigger some code blocks after removing realm object, just trying to trigger that block right before the object removing in the memory. Trying to usage that object after removed from memory, will make some problem and will crash the app.
如果您想在删除领域对象后触发一些代码块,只需尝试在内存中删除对象之前触发该块。从内存中删除后尝试使用该对象会产生一些问题并使应用程序崩溃。
For example:
例如:
DispatchQueue.main.async {
realm.delete()
}
回答by alicanozkara
after spent a day, i figure out with the removeDispatchQueue.main.async
in my realm.delete()
function and finally it worked.
花了一天后,我在我的函数中找出了删除,最后它起作用了。DispatchQueue.main.async
realm.delete()
realm.delete()
to
到
let itemToDelete = counters[indexPath.row]
let realm = try! Realm()
try! realm.write {
realm.delete(itemToDelete)
let predicate = NSPredicate(format: "counterid = \(c.id)")
let children = realm.objects(Details.self).filter(predicate)
realm.delete(children)
}
回答by deebee
In my case I was deleting data from 2 tables at once.. one with a foreign to the other.
在我的情况下,我一次从 2 个表中删除数据……一个与另一个表不同。
let itemToDelete = counters[indexPath.row]
let realm = try! Realm()
try! realm.write {
let predicate = NSPredicate(format: "counterid = \(c.id)")
let children = realm.objects(Details.self).filter(predicate)
realm.delete(children)
realm.delete(itemToDelete) //this should be deleted after
}
But the problem was that I was trying to delete the children of the item that does not exist anymore. Switching the order, solved it!
但问题是我试图删除不再存在的项目的子项。切换顺序,解决了!
##代码##Hope this helps someone else!
希望这对其他人有帮助!