簡體   English   中英

這是調試CoreData並發問題的有效方法嗎?

[英]Is this a valid way of debugging CoreData concurrency issues?

像許多iOS開發人員一樣,我使用CoreData,就像許多使用CoreData的iOS開發人員一樣,我有很難跟蹤線程違規錯誤。 我正在嘗試實現一個調試策略,以便在CoreData並發規則被破壞時拋出異常。 我的嘗試在下面 - 我的問題是,這有效嗎? 它會產生誤報嗎?

簡介:創建NSManagedObject時,請記下該線程。 每當稍后訪問某個值時,檢查當前線程是否與創建線程相同,如果沒有,則拋出異常。

#import "NSManagedObject+DebugTracking.h"
#import "NSObject+DTRuntime.h"
#import <objc/runtime.h>
#import "NSManagedObjectContext+DebugThreadTracking.h"

@implementation NSManagedObject (DebugTracking)

+(void)load {

    [NSManagedObject swizzleMethod:@selector(willAccessValueForKey:) withMethod:@selector(swizzled_willAccessValueForKey:)];
    [NSManagedObject swizzleMethod:@selector(initWithEntity:insertIntoManagedObjectContext:) withMethod:@selector(swizzled_initWithEntity:insertIntoManagedObjectContext:)];

}

- (__kindof NSManagedObject *)swizzled_initWithEntity:(NSEntityDescription *)entity
              insertIntoManagedObjectContext:(NSManagedObjectContext *)context
{
    NSManagedObject *object = [self swizzled_initWithEntity:entity insertIntoManagedObjectContext:context];
    NSLog(@"Initialising an object of type: %@", NSStringFromClass([self class]));

    object.debugThread = [NSThread currentThread];
    return object;
}

-(void)swizzled_willAccessValueForKey:(NSString *)key {

    NSThread *thread = self.debugThread;

    if (!thread) {
        NSLog(@"No Thread set");
    } else if (thread != [NSThread currentThread]) {
        [NSException raise:@"CoreData thread violation exception" format:@"Property accessed from a different thread than the object's creation thread. Type: %@", NSStringFromClass([self class])];
    } else {
        NSLog(@"All is well");
    }

    [self swizzled_willAccessValueForKey: key];
}

-(NSThread *)debugThread {
    return objc_getAssociatedObject(self, @selector(debugThread));
}

-(void)setDebugThread:(NSThread *)debugThread {
    objc_setAssociatedObject(self, @selector(debugThread), debugThread, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}

@end

不,那不是個好主意。 您將部分復制Apple構建到框架中的內容會遇到相當大的麻煩。

如果編輯目標的方案,則可以將-com.apple.CoreData.ConcurrencyDebug 1添加到啟動時傳遞的參數:

並發調試標志

完成后,所有並發沖突都會導致立即崩潰。 您會知道這是一個並發沖突,因為堆棧跟蹤中的“留給我們的一切都是榮譽”消息:

留給我們的只是榮譽

您將看到導致並發沖突的確切代碼行。

您可能還想添加一些其他Core Data調試參數, com.apple.CoreData.SQLDebugcom.apple.CoreData.Logging.stderr 他們不會改變並發調試,但是他們會讓Xcode打印一條消息,讀取CoreData: annotation: Core Data multi-threading assertions enabled這樣你就可以知道它了。

額外的調試標志

不,它無效。 您的代碼假設上下文始終在同一個線程上執行塊。 但實際上它總是運行在同一個QUEUE上,隊列和線程不是一回事。

例如,嘗試使用performBlockAndWait:來檢查它是否使用相同的線程performBlock:運行。 FWIK performBlockAndWait:使用調用它的線程。

您可以添加一個調試標志,該標志顯示有關Core Data執行的操作的大量信息,包括但不限於底層SQL操作。 看到這個答案 請注意,您可以將調試級別從1更改為2或3,以獲得更多調試信息。

我不確定它是否會對您的具體情況有所幫助,但不知道確切的問題和背景,但它應該有所幫助。 此外,您還可以檢查堆棧跟蹤,這對於Xcode 7和8中的多線程調試有很大改進。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM