我在iOS中遇到了一些批处理文档处理问题,并希望能在这里获得一些帮助。我试图实现的过程在iCloud驱动器上使用输入目录,将所有文档提取到那里,并将一条记录添加到iCloud数据库中。现在,'添加iCloud'代码不在这里,但如果我传递正确的指针,很容易做到。我想给用户一个进度条,这样他们就可以检查处理过程并了解它的进展情况。这是我经常在macOS中使用的一种技术,并假设它在iOS中可以正常工作,但我遇到了困难。closeWithCompletionHandler在从后台线程执行时有奇怪的结果
现在奇怪的部分是,如果我删除在后台线程上运行循环的代码并在主线程上运行加载器类,该进程或多或少地起作用。进度条当然不起作用(它永远不会返回主线程),但文档打开代码被称为正确的次数,并且生成进程以打开文档以及所有这些。当我按原样运行它时,我得到一个似乎表明分配或释放进程已中断的异常结束。不要真的发生崩溃,只有不断循环的休息。
的基本过程如下:
用户选择负载选项,并从屏幕和压力机“开始”的目标目录。作为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
segue屏幕为加载器类建立一些计数器属性的观察者。
装载机非常简单。现在它只是通过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:进程到主线程并且工作。去搞清楚。 –