0

当我使用 Core Data 在我的 iOS 应用程序中保存数据时遇到问题。

我的应用程序可以在一秒钟内从服务器接收许多文本消息。

所以我需要将这些消息保存在我的数据库中,现在我在队列中使用 NSOperations 来保存消息(所以你可以想象 NSOperationQueue 中的 NSOperation 的数量)。

问题是在一些指令之后,我阻止了 NSOperationQueue 并且 NSOperation 的数量无限制地增加。

经过一番调查,我发现问题出在保存上下文上,保存上下文阻塞了 NSOperation 并且 NSOperation 我永远不会结束,也永远不会出队,但我无法解决它。

这是我的 NSOperation 代码:

@interface SaveRecievedMessageOperation()

@property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;

@property (nonatomic, strong) AppDelegate *appdelegate;

@property (nonatomic, assign) BOOL executing;

@property (nonatomic, assign) BOOL finished;

@end

@implementation SaveRecievedMessageOperation

@synthesize message;
@synthesize managedObjectContext;
@synthesize appdelegate;
@synthesize executing;
@synthesize finished;



- (id)initWithMessage:(SipMessage *)messageToSave
{
    if (self = [super init]) {
        self.message = messageToSave;

    }
    return self;
}

- (void)main
{

    @autoreleasepool
    {

        self.appdelegate = [[UIApplication sharedApplication] delegate];

        [self managedObjectContext];

        [[NSNotificationCenter defaultCenter] addObserver:self
                                                       selector:@selector(mergeChanges:)
                                                             name:NSManagedObjectContextDidSaveNotification
                                                           object:self.managedObjectContext];

        [self saveMessage];


    }

}

- (NSManagedObjectContext *)managedObjectContext
{

    if (managedObjectContext != nil)
    {

        return managedObjectContext;

    }

    NSPersistentStoreCoordinator *coordinator = [self.appdelegate persistentStoreCoordinator];
    if (coordinator != nil) {
        managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
        [managedObjectContext setPersistentStoreCoordinator:coordinator];
        [managedObjectContext setMergePolicy:NSOverwriteMergePolicy];
    }
    return managedObjectContext;
}

- (void)saveMessage
{

    NSDictionary *header = self.message.headers;

    NSArray *bodies = self.message.bodies;

    SipBody *sipBody;
    NSDictionary* body;
    NSData *ContentData;
    if ([[header valueForKey:@"Content-Type"] rangeOfString:@"application/json"].location != NSNotFound)
    {
        sipBody = [bodies objectAtIndex:0];
        body = [NSJSONSerialization
                JSONObjectWithData:sipBody.content
                options:NSJSONReadingAllowFragments
                error:nil];
    }

    else if ([[header valueForKey:@"Content-Type"] rangeOfString:@"multipart/mixed"].location != NSNotFound)
    {
        for (SipBody *sipB in bodies) {
            if ([[sipB.headers valueForKey:@"Content-Type"] rangeOfString:@"application/json"].location != NSNotFound)
            {
                body = [NSJSONSerialization
                        JSONObjectWithData:sipB.content
                        options:NSJSONReadingAllowFragments
                        error:nil];
            }
            else
            {
                ContentData = [NSData dataWithData:sipB.content];
            }
        }
    }

    else
    {
        return;
    }
    MGMPhone *sender;

    NSArray *senders = [self updatePhonesFromMSISDNsList:[[header valueForKey:@"swfrom"] componentsSeparatedByString:MGMseparator]];
    sender = senders[0];


    NSError *error;
    MGMMessage *aMesage = [MGMMessage createInContext:self.managedObjectContext];
    [aMesage setBoxType:[NSNumber numberWithInteger:BoxTypeIncomingMessage]];
    [aMesage setContent:[body valueForKey:@"Content"]];
    [aMesage setContentType:[header valueForKey:@"Content-Type"]];
    [aMesage setGroupMessage:( [[header valueForKey:@"groupmessage"] isEqualToString:@"true"]
                              ?
  [self saveContext];   
}


#pragma mark core data

- (void)mergeChanges:(NSNotification *)notification
{

        dispatch_async(dispatch_get_main_queue(), ^{
            NSManagedObjectContext *mainContext = [appdelegate managedObjectContext];
            [mainContext performSelector:@selector(mergeChangesFromContextDidSaveNotification:) withObject:notification];


[self setManagedObjectContext:nil];

}

- (void)saveContext
{


    NSError *error = nil;
    if (self.managedObjectContext != nil)
    {
        if ([self.managedObjectContext hasChanges]) {

            BOOL isSaved = [self.managedObjectContext save:&error];
            if(!isSaved){

                NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
                abort();
            }
        }
        else if (![self.managedObjectContext hasChanges]){
             [self setManagedObjectContext:nil];
        }
    }


  }


@end

这是一个共享实例。

#import "CoreDataService.h"

static CoreDataService *sharedService = nil;


@implementation CoreDataService
@synthesize coreDataReceptionQueue;

+ (id)sharedService
{
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        if (sharedService == nil) sharedService = [[self alloc] init];
    });
    return sharedService;
}


- (NSOperationQueue*) coreDataReceptionQueue
{
    if (coreDataReceptionQueue)
    {
        return coreDataReceptionQueue;
    }
    coreDataReceptionQueue = [[NSOperationQueue alloc] init];
    [coreDataReceptionQueue setMaxConcurrentOperationCount:1];
    return coreDataReceptionQueue;
}
@end

这就是我添加新操作的方式

SaveRecievedMessageOperation *op = [[SaveRecievedMessageOperation alloc]initWithMessage:message];
        [[[CoreDataService sharedService] coreDataReceptionQueue] addOperation:op];
4

2 回答 2

0

这可能不是答案,但这是我的观察:

1)您初始化您的操作上下文:NSPrivateQueueConcurrencyType这将迫使您像这样使用上下文:(
[context performBlockAndWait:^{/*you code*/}]您使用“并等待”,因为您不希望您的操作过早完成)。如果您不这样做,您的操作可能会挂起...

==>您可以使用NSConfinementConcurrencyType并保留您的代码来解决这个问题

2)您使用“最大并发”为 1 的操作队列。这是感染串行队列。
您可以简单地保存一个NSPrivateQueueConcurrencyType上下文,然后在其上发出 a[context performBlock:^{/*your code*/}]以达到相同的效果。

于 2013-10-23T12:16:56.443 回答
0

我正在尝试在 iPad 上阅读它,这有点困难。您似乎没有将消息包装到“执行...”块中的 moc - 您必须这样做。此外,您也可以在其中执行 saveContext 。使用异步执行块保存信息和保存,使用同步读取。

于 2013-10-23T11:53:36.150 回答