web-dev-qa-db-fra.com

L'objet Royaume a été supprimé ou invalidé

Lorsque je démarre mon application, j'effectue un appel d'API pour vérifier si de nouvelles données sont disponibles. Les données sont stockées dans la base de données de mon royaume local et certaines d'entre elles sont affichées dans le contrôleur de vue de table initial.

Une fois l'appel de l'API terminé, je vérifie si certaines conditions m'obligent à supprimer une série de données précédentes de la base de données, puis à créer de nouveaux objets. Cependant, lorsque je supprime les anciennes données, mon application se bloque avec l'exception suivante:

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

Cette pile d'appels me laisse supposer que c'est à cause de mon accès en écriture dans la méthode generateLeagueList de FavoriteLeaguesViewController. Ce qui suit est son corps:

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 est du type [League], où League est un objet de domaine. Je suppose que l'exception se produit parce que j'accède aux propriétés des objets League, qui ont été supprimées de la base de données Realm entre temps (car l'appel d'API qui a été lancé dans AppDelegate est maintenant terminé).

Ma question est alors: comment puis-je empêcher cela? Comment puis-je m'assurer qu'il n'y a plus d'accès en écriture/en lecture à aucun des objets League avant de les supprimer?

37
Padarom

Le problème était dans ma classe FavoritesHelper. Il possédait à la fois une propriété favoriteLeagueIDs et favoriteLeagues. J'ai toujours défini les deux et utilisé les identifiants pour une utilisation interne et l'autre propriété chaque fois que je veux des données de ces ligues.

Cela signifiait que toutes les ligues favorites étaient constamment référencées par la propriété favoriteLeagues (du type [League]), ce qui entraînait le blocage de l'application lorsque je voulais les récupérer après leur invalidation.

Ce que j'ai fait pour résoudre ce problème a été de changer la propriété favoriteLeagues en une propriété calculée comme suit:

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

Maintenant, les ligues ne sont plus référencées et sont simplement chargées à partir de la base de données lorsque je dois les lire. Les objets non valides ou supprimés ne sont pas chargés à cause de l'instruction if let (la méthode Realm.objectForPrimaryKey(:key:) renvoie nil dans un tel cas).

9
Padarom

Vous pouvez vérifier si un objet a été supprimé du royaume en appelant object.invalidated. S'il renvoie true, il a été supprimé ou le domaine a été invalidé manuellement.

48
segiddins

J'ai eu un très bon moyen d'attraper une RLMException dans Swift.

Actuellement, Swift ne montre pas où une exception RLMException s'est produite.

Dans Realm/RLMUtil.mm: 266, il existe la définition de RLMException.

Si vous modifiez le code pour générer une erreur Swift,

Xcode peut maintenant vous montrer où l'exception s'est produite.

Maintenant, il fait partie de Swift.

// 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...
}
22
wjiee weofej

Je viens de placer un point d'arrêt à l'intérieur de la méthode:

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

Et sur le panneau de gauche, vous pouvez vérifier la trace de la pile, vous trouverez ici où l’erreur se produit.

11
NazarYavornytskyy

vous pouvez appeler isInvalidated ou invalidated pour juger que l'objet est invalide (OUI) ou non (NON) . vous pouvez également écrire une méthode personnalisée pour définir ce qui est réel invalidate 

cherchez le document, nous verrons une propriété:

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

la invalidated est en lecture seule, mais que signifie isInvalidated?

c'est égal à - (BOOL)invalidated { return invalidated; } 

cela signifie que vous pouvez écrire une méthode personnalisée pour définir ce que vous voulez, à savoir invalidate.

5
Qun Li

Je ne pouvais pas placer de points d'arrêt dans le cadre même de Realm, contrairement à d'autres personnes, mais j'ai placé un point d'arrêt d'exception sur l'ensemble de mon projet:

 enter image description here

Cela m'a permis d'attraper une trace de pile appropriée lorsque l'exception a été levée et de trouver mon bogue.

2
Marcel

Essayez de créer l’élément sur le royaume au lieu de ajouter

Alors: 

try! realm.write {
        realm.add(...)
    }

Remplacer par: 

try! realm.write {
        realm.create(...)
    }

Et ensuite, après la suppression, le domaine devrait fonctionner comme prévu! 

1
Fabio Ciurlia

Ce que vous pouvez faire est d'observer l'objet Results<> renvoyé de votre requête Realm initiale (celle utilisée pour renseigner votre vue liste/table) et de mettre à jour cette liste dans la méthode de rappel de l'observateur chaque fois que la base de données est modifiée.

Assurez-vous simplement que vous utilisez la même instance Realm pour supprimer/modifier l'objet comme celui utilisé pour la requête initiale.

MODIFIER:

Quelques exemples de code:

let realm = Realm()
let results = realm.objects(Favourite.self)
let notificationToken = results.observe { [weak self] (changes) in
    guard let tableView = self?.tableView else { return }
    tableView.reloadData()
}

// Somewhere else
try? realm.write {
    if let favourite = results.first {
         realm.delete(favourite)
    }
}

// OR
if let objectRealm = results.first?.realm {
    try? objectRealm.write {
        objectRealm.delete(results.first!)
    }
}

// Don't forget to stop observing in deinit{}
// notificationToken.invalidate()
0
ken

D'après mon expérience, si vous essayez d'utiliser un objet cible (que vous souhaitez supprimer) après la suppression, l'application se bloque.

Si vous souhaitez déclencher des blocs de code après la suppression d'un objet royaume, essayez simplement de le déclencher juste avant la suppression de l'objet dans la mémoire. Essayer d'utiliser cet objet après avoir été retiré de la mémoire créera un problème et plantera l'application.

Par exemple:

    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.
    }
0
Furkan ASİLTÜRK