Search code examples
objective-ciosmultithreadingnsoperationqueuemailcore

MailCore concurrency support


I'm developing a mail client using the MailCore framework (based on the C library LibEtPan). I'd like to handle the server connection and all the requests in new thread or queue and pushing informations to the main queue for UI updates.

The problem it seems that MailCore variables can't be shared across threads.

@implementation Controller
{
    NSOperationQueue *_queue;
    CTCoreAccount *_account;
    CTCoreFolder *_inbox;
    NSArray *_messages;
}

- (id)init
{
   // stuff

    _queue = [[NSOperationQueue alloc] init];
    
    [_queue addOperationWithBlock:^
     {
         _account = [[CTCoreAccount alloc] init];
         
         BOOL success = [_account connectToServer:@"imap.mail.com" port:993 connectionType:CTConnectionTypeTLS authType:CTImapAuthTypePlain login:@"me@mail.com" password:@"Password"];
         
         if (success)
         {
             CTCoreFolder *inbox = [_account folderWithPath:@"INBOX"];
             NSArray *messages = [inbox messagesFromSequenceNumber:1 to:0 withFetchAttributes:CTFetchAttrEnvelope];
             
             [[NSOperationQueue mainQueue] addOperationWithBlock:^
              {
                  _messages = [messages copy];
                  // UI updates here
              }];
         }
     }];

     // Other stuff
}

Later, for example this method could be called :

- (void)foo
{
    [_queue addOperationWithBlock:^
     {
         CTCoreMessage *message = [_messages objectAtIndex:index];
         
         BOOL isHTML;
         NSString *body = [message bodyPreferringPlainText:&isHTML];
         
         [[NSOperationQueue mainQueue] addOperationWithBlock:^
          {
              // UI Updates
          }];
     }];
}

Here, body is empty because CTCore variables are unable to execute new requests from _queue.

According to this comment, each thread needs is own CTCoreAccount, etc ... Threads on iOS are supposed to have shared memory. I don't exactly understand why reusing the same CTCoreAccount across threads doesn't work, even if references are used in the LibetPan library. How to define a unique CTCoreAccount or CTCoreFolder "attached" to a different thread or queue that can be reused multiple times ?

Any advise would be appreciated. Thank you.


Solution

  • The answer has been given by MRonge here.

    One way is to create an object that contains both the NSOperationQueue (with the maxConcurrentOperationCount=1) and the CTCoreAccount. All work for that account goes through the object, and is only executed on one thread at a time. Then you can one of these objects for each account you want to access.