2016-08-22 31 views
0

我在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 
+0

對此有一個自我解答。強制openWithCompletionHandler:進程到主線程並且工作。去搞清楚。 –

回答

0

對此有了一個自我解答。強制openWithCompletionHandler:進程到主線程並且工作。去搞清楚。