【问题标题】:Programmatic access to the Photos Library on Mac OS X: PhotoKit / Photos Framework for Mac在 Mac OS X 上以编程方式访问照片库:PhotoKit / Photos Framework for Mac
【发布时间】:2015-07-20 14:13:18
【问题描述】:

在 Objective-C 中,有一个 Photos Framework a.k.a. PhotoKit 使 iOS 开发人员能够访问 iPhone 和 iPad 上的照片库并检索图片/视频及其元数据。

Mac 开发人员将如何执行类似的任务? 看来 PhotoKit 仅在 iOS 8.0 中可用。是否有相当于 Mac OS X 的照片框架?

【问题讨论】:

  • 谢谢马特!这样就行了!
  • 上面提到的PhotoKit网页说它也适用于“macOS 10.11+”。
  • @Gabriel 澄清一下,macOS 10.11+ 上有 PhotoKit,但仅限于从照片应用程序构建扩展。与 iOS 上提供的不同,您将无法在 macOS 上通过它访问照片库。

标签: objective-c photos photokit


【解决方案1】:

Media Library Framework 是你要去的地方。

用法:

@import MediaLibrary;

- (void) awakeFromNib
{
  NSDictionary *options = @{
     MLMediaLoadSourceTypesKey: @(MLMediaSourceTypeImage),
     MLMediaLoadIncludeSourcesKey: @[MLMediaSourcePhotosIdentifier]
  };

  MLMediaLibrary *mediaLibrary = [[MLMediaLibrary alloc] initWithOptions:options];
  self.mediaLibrary = mediaLibrary;

  [mediaLibrary addObserver:self
                 forKeyPath:@"mediaSources"
                    options:0
                    context:(__bridge void *)@"mediaLibraryLoaded"];

  [mediaLibrary mediaSources]; // returns nil and starts asynchronous loading
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object 
                        change:(NSDictionary *)change context:(void *)context
{
   if (context == (__bridge void *)@"mediaLibraryLoaded") {
      // Media Library is loaded now, we can access mediaSources
      MLMediaSource *mediaSource = [self.mediaLibrary.mediaSources objectForKey:@"com.apple.Photos"];
   }
}

库背后的概念是,您必须请求它读取对象的属性,该属性返回空引用。然后,您使用 key-value-observer 订阅此属性并等待它加载。然后就可以用同样的原理去检索下一个孩子等等……

【讨论】:

  • 我很难访问此代码示例中的单张照片。您可以详细说明如何使用 MLMediaSource 的任何更改?文档是really bad...
  • 我同意,文档不清楚,您必须使用调试器进行尝试,以了解如何使用 MLMediaObjects...
  • 如何从路径访问照片库图像?示例照片库位于 /Users/admin/Desktop/xyz.photoslibrary。
  • ⚠️ 媒体库框架现已弃用
【解决方案2】:

根据 Pierre F 的回答,我扩展了用于显示所有照片的 url 的代码:

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {

    NSDictionary *options = @{
                              MLMediaLoadSourceTypesKey: @(MLMediaSourceTypeImage),
                              MLMediaLoadIncludeSourcesKey: @[MLMediaSourcePhotosIdentifier]
                              };

    self.mediaLibrary = [[MLMediaLibrary alloc] initWithOptions:options];

    [self.mediaLibrary addObserver:self
                        forKeyPath:@"mediaSources"
                           options:0
                           context:(__bridge void *)@"mediaLibraryLoaded"];

    [self.mediaLibrary.mediaSources objectForKey:MLMediaSourcePhotosIdentifier];
}


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                        change:(NSDictionary *)change context:(void *)context
{
     MLMediaSource *mediaSource = [self.mediaLibrary.mediaSources objectForKey:MLMediaSourcePhotosIdentifier];

    if (context == (__bridge void *)@"mediaLibraryLoaded")
    {
        [mediaSource addObserver:self
                            forKeyPath:@"rootMediaGroup"
                               options:0
                               context:(__bridge void *)@"rootMediaGroupLoaded"];

        [mediaSource rootMediaGroup];
    }
    else if (context == (__bridge void *)@"rootMediaGroupLoaded")
    {
        MLMediaGroup *albums = [mediaSource mediaGroupForIdentifier:@"TopLevelAlbums"];

        for (MLMediaGroup *album in albums.childGroups)
        {
            NSString *albumIdentifier = [album.attributes objectForKey:@"identifier"];

            if ([albumIdentifier isEqualTo:@"allPhotosAlbum"])
            {
                self.allPhotosAlbum = album;

                [album addObserver:self
                        forKeyPath:@"mediaObjects"
                           options:0
                           context:@"mediaObjects"];

                [album mediaObjects];

                break;
            }
        }
    }
    else if (context == (__bridge void *)@"mediaObjects")
    {
        NSArray * mediaObjects = self.allPhotosAlbum.mediaObjects;

        for(MLMediaObject * mediaObject in mediaObjects)
        {
            NSURL * url  = mediaObject.URL;

            NSLog(url.path);
        }
    }
}

【讨论】:

  • 这看起来棒极了,我一回家就试一试!我很好奇,您对如何从 MLMediaObject 获取 GPS 位置有任何想法吗?我现在打开了a question about that,但关于媒体库框架的一般信息很少。
  • 顺便说一句,我试图接受你对我的另一个问题的回答,但它似乎已被删除?如果您使用此代码重新发布它,我会很高兴今晚将赏金奖励给您! :)
  • 我试图效仿你的例子,但@keypath 是什么? Xcode(7.2.1)抱怨,谷歌一直没有帮助:(
  • 对不起,keypath 可以在这里找到github.com/jspahrsummers/libextobjc/blob/master/extobjc/… 或者尝试用字符串值替换
  • 不错的答案,除了@keypath。
【解决方案3】:

虽然这不是一个正式的记录 API,w0lfschild 发布了Apple's PhotoKit framework for macOS 的标头。该 API 看起来与 iOS 非常相似,所以也许您可以仅使用 iOS 文档来弄清楚。除了 MediaLibrary 框架之外,您还可以对库进行更改。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-03-22
    • 2015-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多