objective-c multithreading

Diese Seite verwendet Cookies. Durch die Nutzung unserer Seite erklären Sie sich damit einverstanden, dass wir Cookies setzen. Weitere Informationen

  • objective-c multithreading

    Hallo Leute,
    ich habe mal wieder eine Frage zu multithreading.
    Ich benutzte das Asset Library um mir die Photos zu holen, das in dieser Zeit nicht die UI Blockiert ist benutzte ich ein Operation Block.
    So weit Funktioniert alles nur jetzt ist es extrem langsam und eigentlich funktioniert das Asset Library eh asynchron ich verstehe nicht warum die UI blockiert ist.
    Ich habe wahrscheinlich irgendwas Falsch verstanden ^^ vielleicht könnt ihr mich aufklären.

    Hier der Code.
    Photo Engine:

    Quellcode

    1. #import "LCPhotoEngine.h"
    2. #import "NSDate+LCTimeShiftDate.h"
    3. @implementation LCPhotoEngine
    4. - (void)getAllPhotos
    5. {
    6. NSMutableArray *photos = [NSMutableArray new];
    7. ALAssetsLibrary *assetLibrary = [ALAssetsLibrary new];
    8. [assetLibrary enumerateGroupsWithTypes:ALAssetsGroupSavedPhotos usingBlock:^(ALAssetsGroup *group, BOOL *stop) {
    9. @autoreleasepool {
    10. if (group) { // #1
    11. [group setAssetsFilter:[ALAssetsFilter allPhotos]];
    12. [group enumerateAssetsUsingBlock: ^(ALAsset *asset, NSUInteger index, BOOL *stop) {
    13. if (!asset && (index == NSNotFound)) {
    14. // NotFound
    15. } else {
    16. [photos addObject:asset];
    17. if ([self.delegate respondsToSelector:@selector(photoEngine:didReturnWithAssetRepresentation:)]) {
    18. [self.delegate photoEngine:self didReturnWithAssetRepresentation:asset];
    19. }
    20. }
    21. }];
    22. } else { // #1
    23. if ([self.delegate respondsToSelector:@selector(photoEngine:didFinishWithResults:)]) {
    24. [self.delegate photoEngine:self didFinishWithResults:(NSArray*)photos];
    25. }
    26. } // #1 else
    27. } // autoreleasepool
    28. }
    29. // failureBlock
    30. failureBlock:^(NSError *error) {
    31. NSLog(@"error enumerating AssetLibrary groups %@\n", error);
    32. }];
    33. }
    34. - (NSArray*)filterValidPhotosInAssets:(NSArray*)assets byDateBlocks:(NSArray*)dates
    35. {
    36. __block NSMutableArray *validPhotos = [NSMutableArray new];
    37. [assets enumerateObjectsUsingBlock:^(ALAsset *asset, NSUInteger idx, BOOL *stop) {
    38. if([self isValidAsset:asset byDates:dates]) {
    39. [validPhotos addObject:[UIImage imageWithCGImage:asset.defaultRepresentation.fullScreenImage]];
    40. }
    41. }];
    42. if(!validPhotos.count) {
    43. [validPhotos addObject:[UIImage imageNamed:@"dev_current_record_image@2x.png"]];
    44. }
    45. return validPhotos;
    46. }
    47. - (BOOL)isValidAsset:(ALAsset*)asset byDates:(NSArray*)dates
    48. {
    49. __block NSDate *creationDate = [NSDate dateTimeShiftWithDate:[asset valueForProperty:ALAssetPropertyDate]];
    50. __block BOOL isValid = NO;
    51. [dates enumerateObjectsUsingBlock:^(NSArray *periodOfTime, NSUInteger idx, BOOL *stop) {
    52. NSDate *startDate = periodOfTime.firstObject;
    53. NSDate *enddate = periodOfTime.lastObject;
    54. if([startDate compare:creationDate] == NSOrderedAscending &&
    55. [enddate compare:creationDate] == NSOrderedDescending
    56. ) {
    57. isValid = YES;
    58. }
    59. }];
    60. return isValid;
    61. }
    62. @end
    Alles anzeigen
    Methoden Aufruf:

    Quellcode

    1. NSBlockOperation *photoOperation = [NSBlockOperation blockOperationWithBlock:^{ [self.photoEngine getAllPhotos]; }];
    2. [self.tableDataOperationQueue addOperation:photoOperation];
    Alles anzeigen



    ich bedanke mich schon einmal im voraus für die Hilfe.
  • Du musst normalerweise NSOperation subclasen und isConcurrent überschreiben, damit asynchron gearbeitet wird.

    Mit NSBlockOperation habe ich noch nie gearbeitet. Aber wenn man da erst ne Subclass erstellen muss um dann einen async. Block losschicken zu können, der einem eigentlich das Subclassen spart, dann werde ich das wohl auch nicht tun.

    Gruß
    Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
  • ja ich finde es auch cool das es so einfach geht ^^.
    hier habe ich noch einmal den text aus der documentation

    Quellcode

    1. The NSBlockOperation class is a concrete subclass of NSOperation that manages the concurrent execution of one or more blocks

    aber ich finde es komisch warum es jetzt so lange dauert um die Bilder aus zu lesen
  • Lustig das kapiere ich nicht :(
    also meine delegate Methoden werden sofort aufgerufen es gibt keine Zeitverzögerung.
    Hier einmal die Methoden:

    didReturnWithAssetRepresentation

    Quellcode

    1. - (void)photoEngine:(LCPhotoEngine*)photoEngine didReturnWithAssetRepresentation:(ALAsset*)asset{ if(!self.wasFoundFirstValidPhoto) { if([self.photoEngine isValidAsset:asset byDates:[LCPersistanceEngine datesByDatesBlockWithActivityName:self.activityName]]) { [self setActivityImageViewWithRandomImage:[UIImage imageWithCGImage:asset.defaultRepresentation.fullScreenImage]]; self.foundFirstValidPhoto = YES; } }

    setActivityImageViewWithRandomImage:

    Quellcode

    1. - (void)setActivityImageViewWithRandomImage:(UIImage*)randomImage{ self.activityImageView.image = randomImage; [self.activityIndicatorView removeFromSuperview];
    2. }


    die zwei Methoden werden sofort aufgerufen nur nur das setzten des Bildes in den ImageView dauert jetzt extrem lange.
    Eigentlich dauert jetzt alles was ich mit der UI mach sehr lange.
    Woran kann das liegen ?
    Kann es daran liegen weil ich in einem anderen OperationQueue arbeite ?
  • Dann wird zu 99.9% dein setImage: ... bluBlab nicht aus dem Hauptthread aufgerufen. Nachrichten an UI Elemente mussen immer im Hauptthread abgeschickt werden, sonst gibts ein undefiniertes Verhalten - meistens ein paar Sekunden Verzögerung.

    Nimm z.B. eine der performSelectorInMainThread Methoden. Oder über die c API:

    Quellcode

    1. dispatch_async(dispatch_get_main_queue(), ^{
    2. // code....
    3. });
    Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
  • Wenn du Code async. ausführen willst, brauchst du einfach nur:

    Quellcode

    1. dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    2. dispatch_async(queue, ^{
    3. // code
    4. });


    Einen Autoreleasepool musst du nicht erzeugen (wenn ich das noch richtig in Erinnerung habe, brauchst du den bei der NSOperation API auch nicht, der wird hier auch von System angelegt)
    Seminare, Artikel, Code. ObjectiveCeeds - alles für die Apfelzucht.
  • Setzt du das Bild etwa im Backgroundthread? Das darfst du natürlich nicht. Du musst dem MsinThread eine Nachricht schicken, dass das Bild da ist und der muss dieses dann in das ImageView setzen.

    Gruß

    Claus
    2 Stunden Try & Error erspart 10 Minuten Handbuchlesen.

    Pre-Kaffee-Posts sind mit Vorsicht zu geniessen :)