У меня возникли проблемы с обработкой пакетного документа в 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
Получил ответ самостоятельно. Принудило openWithCompletionHandler: обработал основной поток, и он сработал. Идите фигуру. –