2016-08-22 2 views
0

У меня возникли проблемы с обработкой пакетного документа в iOS, и я надеялся, что смогу помочь здесь. Процесс, который я пытаюсь реализовать, использует входной каталог на диске iCloud, извлекает все документы там и добавляет одну запись в базу данных iCloud для каждого. Прямо сейчас, код «добавить iCloud» здесь не здесь, но его достаточно легко сделать, если я передаю правильные указатели. Я хотел бы дать пользователю индикатор выполнения, чтобы они могли проверить обработку и получить представление о том, как хорошо это происходит. Этот метод, который я часто использую в macOS, и просто предположил, что он будет работать нормально в iOS, но у меня возникают трудности.closeWithCompletionHandler имеет нечетные результаты, когда выполняется из фоновой темы

Теперь странная часть этого вопроса заключается в том, что если я удалю код, который запускает цикл в фоновом потоке и запускает класс загрузчика в основном потоке, процесс будет работать более или менее. Конечно, индикатор выполнения не работает (он никогда не возвращает основной поток), но код открытия документа называется правильным числом раз, и процессы порождаются, чтобы открыть документы и все такое. Когда я запускаю его как есть, я получаю abend, похоже, что это указывает на то, что процесс allocate или deallocate нарушен. На самом деле не получилось крушение, а только перерыв, который постоянно петли.

Основной процесс выглядит следующим образом:

Пользователь выбирает опцию загрузки и целевой каталог с экрана и нажимает кнопку «идти». Как часть segue, процесс загрузчика создается и ждет немного начала (есть лучшие способы сделать это, но они могут подождать, пока я не получу базовый процесс)

Пользователь перешел на другой экран, который отображает индикатор выполнения. Вот код для этого:

// 
// LoadPopover.m 
// TestFindIt 
// 
// Created by Joe Ruth on 7/16/16. 
// Copyright © 2016 Joe Ruth. All rights reserved. 
// 

#import "LoadPopover.h" 

@interface LoadPopover() 
@end 

@implementation LoadPopover; 

@synthesize localSecondViewController, localLoadCloudDBClass, loadProgressBar,  screenReloadDirectory; 
@synthesize loadedDocuments; 

- (void)viewDidLoad { 
    [super viewDidLoad]; 
    // Do any additional setup after loading the view. 
} 

- (void)didReceiveMemoryWarning { 
    [super didReceiveMemoryWarning]; 
    // Dispose of any resources that can be recreated. 
} 

- (IBAction)pressedDoneButton:(id)sender { 

    [self dismissViewControllerAnimated:YES completion:nil]; 
} 


-(void)viewDidAppear:(BOOL)animated { 

    [localLoadCloudDBClass addObserver:self 
          forKeyPath:@"iterationcounter" 
           options:NSKeyValueObservingOptionNew 
           context:NULL]; 

    [localLoadCloudDBClass addObserver:self 
          forKeyPath:@"totalcounter" 
           options:NSKeyValueObservingOptionNew 
           context:NULL]; 

    loadProgressBar.progress = 0.00; 

    self.loadedDocuments = [[NSMutableArray alloc] init]; 
    localLoadCloudDBClass.loadedDocuments = self.loadedDocuments; 

    [localLoadCloudDBClass LoadCloudDBClassRun:self]; 

} 


- (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)objectchange:(NSDictionary *)changecontext:(void *)context 
    { 

     [[NSOperationQueue mainQueue] addOperationWithBlock:^{ 


     int iterationcounter; 
     int totalcounter; 

     iterationcounter = (int) localLoadCloudDBClass.iterationcounter; 
     totalcounter = (int) localLoadCloudDBClass.totalcounter; 

     if (totalcounter != 0) { 
      loadProgressBar.progress = (float) iterationcounter/(float) totalcounter;} 
     else { 
      loadProgressBar.progress = 0.00;} 

    }]; 
} 

@end 

экрана устанавливает переход наблюдателя для некоторых счетчиков свойств для класса загрузчика.

Погрузчик довольно прост. Сейчас это всего лишь страницы через базу данных iCloud и запускает процесс открытия документа для каждой записи в базе данных. В какой-то момент мне нужно будет немного поучаствовать в процессе открытия документа, но сейчас это доказательство концепции.

// 
// LoadCloudDBClass.m 
// TestFindIt 
// 
// Created by Joe Ruth on 7/15/16. 
// Copyright © 2016 Joe Ruth. All rights reserved. 
// 

#import "LoadCloudDBClass.h" 
#import "Item.h" 
#import "SaveObject.h" 
#import "SaveObjectUIDocument.h" 

@implementation LoadCloudDBClass 

@synthesize localFindItDataController, screenReloadDirectory, localLoadPopover, iterationcounter, totalcounter; 
@synthesize loadedDocuments; 

- (void) LoadCloudDBClassRun:(NSObject *) parameterTestFinditCaller { 

    dispatch_queue_t backgroundQueue = dispatch_queue_create("Background Queue",NULL); 

    dispatch_async(backgroundQueue, ^{ 

     NSError *error; 
     unsigned long check_count; 
     unsigned long total_count; 
     NSURL *fileURL; 
     int stopper; 

     __block BOOL blockSuccess = NO; 
     __block BOOL blockCalled = NO; 

     [self setIterationcounter:(NSInteger) 0]; 
     [self setTotalcounter:(NSInteger) 0]; 

     NSFileManager *fm = [NSFileManager defaultManager]; 
     NSURL *rootURL = [fm URLForUbiquityContainerIdentifier:nil]; 
     NSURL *newFolderTemp = [rootURL URLByAppendingPathComponent:@"Documents" isDirectory:YES]; 
     NSURL *newFolder = [newFolderTemp URLByAppendingPathComponent:screenReloadDirectory isDirectory:YES]; 

     NSNumber *isDirectory; 
     if (![newFolder getResourceValue:&isDirectory forKey:NSURLIsDirectoryKey error:&error]) {return;} 

     NSArray *theFiles = [fm contentsOfDirectoryAtURL:newFolder 
           includingPropertiesForKeys:[NSArray arrayWithObject:NSURLNameKey] 
                options:NSDirectoryEnumerationSkipsHiddenFiles 
               error:nil]; 

     [self setTotalcounter:(NSInteger) [theFiles count]]; 

     total_count = [theFiles count]; 
     check_count = 0; 

     while ((check_count < total_count) && (total_count != 0)) { 

      fileURL = [theFiles objectAtIndex:check_count]; 

      SaveObjectUIDocument *tempdoc = [[SaveObjectUIDocument alloc] initWithFileURL:fileURL]; 
      //tempdoc.loadedDocuments = loadedDocuments; 

      long set_iterationcounter = iterationcounter + 1; 
      [self setIterationcounter:(NSInteger) set_iterationcounter]; 

      [tempdoc openWithCompletionHandler:^(BOOL success) { 
       NSLog (@" try Open"); 
       if (success) { 
        blockSuccess = success; 
        blockCalled = YES; 
        //[self.loadedDocuments addObject:tempdoc]; 
        NSLog(@"Opened");} 
       else 
        {NSLog(@"Not Opened");} 

      }]; 

      blockCalled = NO; 

      NSDate *loopUntil = [NSDate dateWithTimeIntervalSinceNow:10]; 
      while (!blockCalled && [loopUntil timeIntervalSinceNow] > 0) 
      { 
       [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode 
             beforeDate:loopUntil]; 
      } 

      check_count++; 

     } 

     stopper=5; 

    }); 


} 

@end 

Кодирование документа выглядит следующим образом:

Вот файл .h

// 
// SaveObject.h 
// TestFindIt 
// 
// Created by Joe Ruth on 1/10/16. 
// Copyright © 2016 Joe Ruth. All rights reserved. 
// 

#import <Foundation/Foundation.h> 

@interface SaveObject : NSObject <NSCoding> { 

    NSData *_sxmlData; 

} 

- (id)initWithData:(NSData *)in_xmlData; 

@property (nonatomic, copy) NSData *sxmlData; 

@end 

Здесь сопровождающий .m файл

// 
// SaveObject.m 
// TestFindIt 
// 
// Created by Joe Ruth on 1/10/16. 
// Copyright © 2016 Joe Ruth. All rights reserved. 
// 

#import "SaveObject.h" 

@implementation SaveObject 

@synthesize sxmlData = _sxmlData; 

- (id)initWithData:(NSData *)in_xmlData { 
    if ((self = [super init])) { 
     self.sxmlData = in_xmlData; 


    } 
    return self; 
} 

- (id)init { 
    return [self initWithData:nil]; 
} 

#pragma mark NSCoding 

#define kVersionKey @"Version" 
#define kDataKey @"Data" 
#define kSaveObjectXMLData @"SaveObjectXMLData" 

//- (void)encodeWithCoder:(NSCoder *)encoder { 
// [encoder encodeInt:1 forKey:kVersionKey]; 
// [encoder encodeObject:self.sxmlData forKey:kDataKey]; 
//} 

//- (id)initWithCoder:(NSCoder *)decoder { 
// [decoder decodeIntForKey:kVersionKey]; 
// NSData * outxmlData = [decoder decodeObjectForKey:kDataKey]; 
// NSLog(@">>>>>>>>>>>>>>>>>>> %@",outxmlData); 
// return [self initWithData:outxmlData]; 
//} 

#pragma mark - 

#pragma mark NSCoding Protocol 

- (void)encodeWithCoder:(NSCoder *)coder { 
    [coder encodeObject:self.sxmlData forKey:kSaveObjectXMLData]; 
} 

- (id)initWithCoder:(NSCoder *)coder { 
    self = [super init]; 

    if (self != nil) { 


     self.sxmlData = [coder decodeObjectForKey:kSaveObjectXMLData]; 
    } 

    return self; 
} 

@end 

Здесь высокий уровень кодирование документа .h файл

// 
// SaveObjectUIDocument.h 
// TestFindIt 
// 
// Created by Joe Ruth on 1/10/16. 
// Copyright © 2016 Joe Ruth. All rights reserved. 
// 

#import <UIKit/UIKit.h> 

@class SaveObject; 


@interface SaveObjectUIDocument : UIDocument { 

    SaveObject *_SaveObject; 

} 

@property (strong, nonatomic) SaveObject *SaveObject; 

@end

И прилагаемый файл .m. Позже сюда добавится код добавления iCloud, и мне нужно будет убедиться, что открытый адрес объекта MOC был передан правильно.

// 
// Created by Joe Ruth on 1/10/16. 
// Copyright © 2016 Joe Ruth. All rights reserved. 
// 

#import "SaveObjectUIDocument.h" 
#import "SaveObject.h" 

#define kArchiveKey @"SaveObjectXMLData" 

@interface SaveObjectUIDocument() 
@property (nonatomic, strong) NSData * data; 
@end 

@implementation SaveObjectUIDocument; 

@synthesize SaveObject = _SaveObject; 

- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { 
    if ([contents length] > 0) { 
     NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:contents]; 
     self.SaveObject = [unarchiver decodeObjectForKey:kArchiveKey]; 
     [unarchiver finishDecoding];} 
    else { 
     self.SaveObject = [[SaveObject alloc] initWithData:nil];} 
    return YES; 
} 


- (id)contentsForType:(NSString *)typeName error:(NSError *__autoreleasing *)outError { 
    NSMutableData *data = [[NSMutableData alloc] init]; 
    NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data]; 
    [archiver encodeObject:self.SaveObject forKey:kArchiveKey]; 
    [archiver finishEncoding]; 

    return data; 

} 

- (void)handleError:(NSError *)error userInteractionPermitted:(BOOL)userInteractionPermitted { 
    NSLog(@"Error: %@ userInfo=%@", error.localizedDescription, error.userInfo); 
    [super handleError:error userInteractionPermitted:userInteractionPermitted]; 
} 


@end 
+0

Получил ответ самостоятельно. Принудило openWithCompletionHandler: обработал основной поток, и он сработал. Идите фигуру. –

ответ

0

Получил ответ самостоятельно. Принудило openWithCompletionHandler: обработал основной поток, и он сработал. Идите фигуру.

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