2015-08-06 4 views
26

Когда я запускаю свое приложение, я выполняю вызов API, чтобы узнать, имеются ли новые данные. Данные хранятся в моей локальной базе данных Realm, а некоторые из них отображаются в начальном контроллере табличного представления.Объект Realm удален или аннулирован

Как только вызов 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 

Этого вызова позволяет мне предположить, что это из-за мой доступ к записи в generateLeagueList методы FavoriteLeaguesViewController в. Следующее является его тело:

var favorites = FavoritesHelper.sharedInstance.favoriteLeagues 
favorites.sort { $0.sport < $1.sport } 

for favorite in favorites { 
    // Add to array, which we can later use for cellForRowAtIndexPath 
} 

favorites относится к типу [League], где League является Realm объекта. Я предполагаю, что это исключение происходит из-за того, что я обращаюсь к свойствам объектов League, которые были удалены из базы данных Realm в среднем времени (потому что вызов API, который был запущен в AppDelegate, теперь завершен).

Мой вопрос тогда: как я могу предотвратить это? Как я могу убедиться, что до любого удаления объектов League больше нет записи/чтения-доступа до их удаления?

+0

попробуйте эту ссылку может помочь с u http://stackoverflow.com/questions/29432191/realm-crashes-with-rlmexception-object-has-been-deleted-or-invalidated –

ответ

9

Вопрос был в моем классе FavoritesHelper. Он имел как favoriteLeagueIDs, так и favoriteLeagues. Я всегда устанавливал их оба и использовал идентификаторы для внутреннего использования и другого свойства, когда мне нужны данные из этих лиг.

Это означало, что все любимые лиги постоянно ссылались на свойство favoriteLeagues (типа [League]), что привело к сбою приложения, когда я хотел получить их после того, как они были признаны недействительными.

Что я сделал, чтобы исправить это, было изменить свойство favoriteLeagues к расчетному собственности следующим образом:

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

Теперь лиги будут больше не ссылаются и просто загружаются из базы данных, когда мне нужно читать их. Недействительные или удаленные объекты не загружаются из-за оператора if let (метод Realm.objectForPrimaryKey(:key:) возвращает nil в таком случае).

35

Вы можете проверить, был ли объект удален из Царства, вызвав object.invalidated - если он возвращает true, то он был удален или Королевство аннулировано вручную.

+15

Что нужно предпринять эта точка, повторный запрос для объекта из Realm? @segiddins – kbpontius

+0

@kbpontius либо это, либо очистить ссылку на этот объект, в зависимости от вашего использования. –

16

У меня действительно хороший способ поймать исключение RLM в Swift.

В настоящее время Swift не показывает, где произошло исключение RLMException.

В Realm/RLMUtil.mm: 193 существует определение для исключения RLMException.

Если изменить код, чтобы создать быструю ошибку,

Xcode теперь может показать вам, где произошло исключение.

Теперь это часть Свифта.

// Realm/RLMUtil.mm:193 
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... 
} 
+0

Очень хорошая исследовательская работа! –

+3

Можете ли вы внести свой вклад в проект Realm Swift? Это помогло бы многим людям – mylovemhz

+0

@wjiee weofej, пожалуйста, объясните свое решение, я не смог поймать RLMException в быстром. Спасибо –

5

Я просто поместить точку останова внутри метода:

// Realm/RLMUtil.mm:193 
static NSException *RLMException(NSString *reason, NSDictionary *additionalUserInfo) { 
    // ... 
} 

А на левой панели вы можете проверить трассировки стека, здесь вы можете найти, где ошибка бросками.

1

я не смог поставить точки останова внутри самой структуры Realm, как другие предлагали, но вместо этого поместил точку останова исключение на весь мой проект:

enter image description here

Это позволило мне поймать правильный трассировки стека, когда исключение было брошено, и найти мою ошибку.

2

вы можете позвонить isInvalidated или invalidated, чтобы судить о том, что объект недействителен (ДА) или нет (НЕТ). вы также можете написать пользовательский метод, чтобы определить, что является реальным invalidate

взгляд на документ, то мы увидим свойство:

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

invalidated только для чтения, но что isInvalidated значит?

это равняется - (BOOL)invalidated { return invalidated; }

это означает, что вы можете написать специальный метод, чтобы определить, что является реальным invalidate вы хотите.

Смежные вопросы