2016-08-08 78 views
3

I umgewandelt haben einige PHAsset-UIImage:Wie vergleichen PHAsset zu UIImage

PHImageManager *manager = [PHImageManager defaultManager]; 
      [manager requestImageForAsset:asset 
           targetSize:PHImageManagerMaximumSize 
           contentMode:PHImageContentModeDefault 
            options:requestOptions 
          resultHandler:^void(UIImage *image, NSDictionary *info) { 
           convertedImage = image; 
           [images addObject:convertedImage]; 
          }]; 

Jetzt möchte ich, so etwas tun:

[selectedAssets removeObject:image]; 

wo selectedAssets ist ein Array von PHAsset und image ist ein UIImage

so habe ich das isEqual wie folgt implementiert:

- (BOOL)isEqual:(id)other { 
    if (other == self) 
     return YES; 
    if (!other || ![[other class] isEqual:[self class]]) 
     return NO; 

    NSData *data1 = UIImagePNGRepresentation(self.image); 
    NSData *data2 = UIImagePNGRepresentation(((TINSelectedImage*)other).image); 

    return [data1 isEqual:data2]; 
} 

Aber es funktioniert nicht!

Antwort

6

Sie sollten keine Bilder vergleichen, sondern PHAssets oder deren einzigen nützlichen Teil namens localIdentifier.

Die Sache, die Sie suchen, um zwischen Vermögenswerten zu unterscheiden, heißt localIdentifier Eigenschaft von PHAsset.

Die Apple-Docs definiert es als:

A unique string that persistently identifies the object. (read-only) 

Leider diese Antwort wird ein bisschen breit sein, weil ich Ihren Ansatz nicht hier mögen.

Wenn ich Sie wäre, würde ich es tun, wie folgt:

Zuerst erstellen Sie eine benutzerdefinierte Klasse, machen wir es PhotoInfo nennen. (Sie müssen das nicht wirklich tun, wenn Sie nicht daran interessiert sind, viele Informationen über Ihre Fotos zu speichern. Wenn dies der Fall ist, verwenden Sie die PFFetchResults von PHAsets direkt, wenn Sie möchten. Ich werde jedoch mit CustomClass gehen).

in PhotoInfo.h:

#import <Foundation/Foundation.h> 
@interface PhotoInfo : NSObject 

@property NSString *localIdentifier; 

@end 

Anstatt nun eine Reihe von Bildern zu verwenden, benutzen Sie diese benutzerdefinierte Klasse, die Sie erstellt, die Local enthalten werden. Wie folgt aus:

PhotoInfo *photo = [[PhotoInfo alloc] init]; 
photo.localIdentifier = asset.localIdentifier; 

Angenommen, Sie Bilder aus der Galerie holen wollen, würden Sie so etwas tun:

-(PHFetchResult*) getAssetsFromLibrary 
{ 
    PHFetchResult *allPhotos; 
    PHFetchOptions *allPhotosOptions = [[PHFetchOptions alloc] init]; 
    allPhotosOptions.sortDescriptors = @[[NSSortDescriptor sortDescriptorWithKey:@"creationDate" ascending:NO]]; //Get images sorted by creation date 

    allPhotos = [PHAsset fetchAssetsWithMediaType:PHAssetMediaTypeImage options:allPhotosOptions]; 

    return allPhotos; 
} 

Um die Datenquelle zu füllen, haben Sie so etwas wie:

NSMutableArray *yourPhotoDataSource = [[NSMutableArray alloc] init]; 
PHFetchResult * assets = [self getAssetsFromLibrary]; 
for(PHAsset *asset in assets) 
     { 
      PhotoInfo *photo = [PhotoInfo new]; 
      photo.localIndentifier = asset.localIdentifier; 
      [yourPhotoDataSource addObject:photo]; 

     } 

Nehmen wir an, Sie müssen diese Bilder irgendwo anzeigen, und Sie brauchen ein aktuelles Bild dafür, also werden Sie so etwas tun, um das Bild zu erhalten:

-(void) getImageForAsset: (PHAsset *) asset andTargetSize: (CGSize) targetSize andSuccessBlock:(void (^)(UIImage * photoObj))successBlock { 
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
     PHImageRequestOptions *requestOptions; 

     requestOptions = [[PHImageRequestOptions alloc] init]; 
     requestOptions.resizeMode = PHImageRequestOptionsResizeModeFast; 
     requestOptions.deliveryMode = PHImageRequestOptionsDeliveryModeFastFormat; 
     requestOptions.synchronous = true; 
     PHImageManager *manager = [PHImageManager defaultManager]; 
     [manager requestImageForAsset:asset 
          targetSize:targetSize 
          contentMode:PHImageContentModeDefault 
           options:requestOptions 
         resultHandler:^void(UIImage *image, NSDictionary *info) { 
          @autoreleasepool { 

           if(image!=nil){ 
            successBlock(image); 
           } 
          } 
         }]; 
    }); 

} 

Lassen Sie uns jetzt sagen, Sie diese Bilder in einem Tableview angezeigten, in Ihrem cellForRowAtIndexPath, rufen Sie die oben genannten Methode wie folgt:

//Show a spinner 
    // Give a customizable size for image. Why load the memory with full image if you don't need to show it? 
[self getImageForAsset:asset andTargetSize:yourDesiredCGSizeOfImage andSuccessBlock:^(UIImage *photoObj) { 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       //Update UI of cell 
       //Hide the spinner 
       cell.thumbNail.image = photoObj; 
      }); 
     }]; 

Jetzt werden Sie Bilder asynchron mit glatten Benutzererfahrung und Speichern von Speicher zu laden Außerdem werden nur die Bilder angezeigt, die benötigt werden, anstatt alle zu speichern. (Sie können die Leistung durch Einführung von Caching noch verbessern, aber das ist nicht der Punkt hier).

Schließlich zu Ihrer Frage, um ein bestimmtes Bild zu entfernen, benötigen Sie nur den localIdentifier, weil es für jeden PHAsset oder Index einzigartig ist.

Nehmen wir an, Sie löschen eine Zelle in Ihrem TableView, die das bestimmte Bild zeigt, das Sie jetzt entfernen möchten.

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { 

if (editingStyle == UITableViewCellEditingStyleDelete) { 
    PhotoInfo *photo = [yourPhotoDataSource objectAtIndex:indexPath.row]; 
    [yourPhotoDataSource removeObject:photo]; 
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] 
        withRowAnimation:UITableViewRowAnimationFade]; 


} 
} 

Wenn Sie kein Tableview/Collection mit und wissen nicht, den Index des Objekts können Sie schnell Aufzählung auf Ihrem Array verwenden, aber dann müssen Sie die Local des Objekts weiß, Sie wollen löschen:

-(void) deletePhotoWithIdentifier:(NSString *) identifierStr{ 
NSMutableArray *dummyArray = [[NSMutableArray alloc] initWithArray:yourPhotoDataSource]; //created because we can't modify the array we are iterating on. Otherwise it crashes. 
[dummyArray enumerateObjectsWithOptions:NSEnumerationReverse usingBlock:^(PhotoInfo *p, NSUInteger index, BOOL *stop) { 
    if ([p.localIndentifier isEqualToString:idenfierStr]) { 
     [yourPhotoDataSource removeObjectAtIndex:index]; 
    } 
}]; 

} 
+1

Ausgezeichnete Antwort – iOSGeek

+1

So gründlich eine Antwort/Beispiel, wie Sie (möglicherweise) brauchen. – malaki1974