我需要在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层次结构而监视更改?