Apple Photos:在macOS上使用MediaLibrary观察MLMediaGroup的更改

时间:2018-11-02 14:25:03

标签: objective-c macos cocoa

我需要在macOS上的应用程序中显示Apple Photos的相册结构。我能找到的唯一方法是MediaLibrary框架。我可以使用MLMediaGroup类遍历树结构,而不会出现问题。但是看着它的变化让我感到困惑。我希望我需要为每个媒体组订阅KVO通知,并观察属性的变化。

但是实际上,当我在“照片”中创建新相册/文件夹时,我收到通知,通知rootMediaGroup已更改,并且该组以及所有子组的地址也已更改。这似乎很奇怪,因为现在我必须重建整个专辑层次结构。就像观看目录更改并获得不透明的通知(例如“文件系统中的某些内容已更改”)一样,每次用户在$ HOME内的某个深处修改目录时,都无需进一步的详细信息。

我正在使用Objective-C(实际上我需要将其与C ++集成),尽管快速的示例也可能给我一个提示。下面我提供一个最小的例子来说明这个问题。

PhotosObserver.h

#import <Foundation/Foundation.h>
#import <MediaLibrary/MediaLibrary.h>

@interface PhotosObserver: NSObject
{
    @private
    MLMediaLibrary *ml;
    MLMediaSource *src;
    MLMediaGroup *root;
}

@property(nonatomic, retain, nullable, readonly) MLMediaLibrary *ml;
@property(nonatomic, retain, nullable, readonly) MLMediaSource *src;
@property(nonatomic, retain, nullable, readonly) MLMediaGroup *root;

@end

PhotosObserver.m

#include "PhotosObserver.h"

static void* CTX_MEDIASOURCE         = &CTX_MEDIASOURCE;
static void* CTX_MEDIAGROUP          = &CTX_MEDIAGROUP;

static NSString* KPATH_SOURCES = @"mediaSources";
static NSString* KPATH_GROUPS  = @"rootMediaGroup";

@implementation PhotosObserver

@synthesize ml;
@synthesize src;
@synthesize root;

-(id)init {
    if(self = [super init]) {
        self->ml = [[MLMediaLibrary alloc] init];
        [self->ml addObserver: self forKeyPath:KPATH_SOURCES options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:CTX_MEDIASOURCE];
        [self->ml mediaSources];
    }
    return self;
}

-(void)dealloc {
    @try {
        [self.ml removeObserver:self forKeyPath:KPATH_SOURCES context:CTX_MEDIASOURCE];
        [self.src removeObserver:self forKeyPath:KPATH_GROUPS context:CTX_MEDIAGROUP];
    }
    @catch(NSException *) {}
}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if(CTX_MEDIASOURCE == context)
    {
        NSLog(@"Loaded mediaSources");
        self->src = [self->ml.mediaSources objectForKey:/*@"com.apple.Photos"*/MLMediaSourcePhotosIdentifier];
        assert(self->src);
        [self.src addObserver: self forKeyPath:KPATH_GROUPS options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:CTX_MEDIAGROUP];
        [self.src rootMediaGroup];
    }
    else if(CTX_MEDIAGROUP == context)
    {
        MLMediaGroup *old = self->root;
        if(!old)
            NSLog(@"Loaded rootMediaGroup");
        self->root = self.src.rootMediaGroup;
        if(old && old != self.root)
        {
            NSLog(@"Oops, root group has changed: %@ -> %@", old, self.root);
        }
    }
}


@end

当我运行程序并创建文件夹/相册或在“照片”中重命名相册时,我收到有关根组已更改的通知。由于某种原因,我在100%的情况下都没有收到通知,但是无论如何还是很频繁。

问:为什么rootMediaGroup根本没有更改,因为用户无法在“照片”用户界面中进行更改?

问:如何在每次小用户修改后无需重新扫描整个MLMediaGroup层次结构而监视更改?

0 个答案:

没有答案