Swift 5.2 中的 iTunes 库框架

ITunes Library Framework in Swift 5.2

我到处搜索,但无法找到如何使用 Apple ITunesLibraryFramework 的快速示例。我一直在尝试弄清楚如何在 Swift 5.2.

中使用这个框架

我想直接从音乐库中获取信息,而不必依赖 XML 库导出文件。

我的 playground 中有以下代码,但打印出来的内容不清晰。我将如何访问播放列表和媒体项目的字段并能够以人类可读的形式阅读它们?

我已经在项目中安装了框架。这是我的项目游乐场代码:

import Foundation
import iTunesLibrary

var library:ITLibrary

do {
    let library = try ITLibrary(apiVersion: "1.1")
    let mediaItems = library.allMediaItems
    let playlists = library.allPlaylists
    print("Media Folder Location - \(String(describing: library.mediaFolderLocation))")
    print("\nPlaylists - \(playlists)")
    print("\nTracks - \(mediaItems)")
} catch let error as NSError {
    print(error)
}

这是我导入的 ITLibrary.m 文件 header:

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

当我 运行 在项目操场中使用上述代码时,我得到的只是播放列表和媒体项的一堆二进制数据。我想要做的就是遍历数据并从库中收集信息以供我的程序使用。应该是很简单的东西,但是我还没找到。

编辑: - 在使用@Vincent 的回答后,我 运行 使用以下代码进入另一个问题:

import Foundation
import iTunesLibrary

let library = try ITLibrary(apiVersion: "1.1")
typealias tracks = [NSNumber:TrackInfo]
var trackInfo = TrackInfo()

struct TrackInfo {
    var title = ""
    var artist = ""
    var album = ""
    var totalTime = 0
    var year = 0
    var persistentID = ""
    var location:URL!
}

let songs = library.allMediaItems
let playlists = library.allPlaylists

for playlist in playlists {
    if playlist.name.lowercased().contains("test-") {
        print("New Playlist---------------\nName: \(playlist.name)")
        for song in playlist.items {
            trackInfo.title = song.title
            print("\n\nNew Track-----------------\nTitle: \(trackInfo.title)")
            if song.artist?.name != nil {
                trackInfo.artist = song.artist?.name as! String
            }
            print("Artist: \(trackInfo.artist)")
            trackInfo.album = song.album.title!
            print("Albumn Name: \(trackInfo.album)")
            trackInfo.totalTime = song.totalTime
            print("Total Time: \(trackInfo.totalTime)")
            trackInfo.year = song.year
            print("Year: \(trackInfo.year)")
            trackInfo.location = song.location!
            print("Location: \(trackInfo.location!)")
            var persistentID = song.persistentID
            tracks.updateValue(song.persistentID, trackInfo)
        }
    }
}

我遇到的问题是将曲目信息添加到 trackInfo 字典中。我正在尝试使用轨道 persistentID (NSNumber) 作为我已声明的字典的键。出于某种原因,它不允许我使用它。

以下是如何让它打印每个播放列表和曲目:

每个 ITLibPlaylistITLibMediaItem 对象包含有关每个 playlist/media 项目的许多信息。要仅获取每个的 name/title,您将必须遍历结果以检索它们。

对于下面的示例,打印了每个播放列表的名称。

    print("\nPlaylists -")
    for playlist in playlists {
        print(playlist.name)
    }

这将打印(例如):

Playlists -
Library
Music

对于下面的这个例子,打印了每个曲目的名称。

    print("\nTracks -")
    for mediaItem in mediaItems {
        print(mediaItem.title)
    }

这将打印(例如):

Tracks -
Ev'ry Time We Say Goodbye
My Favorite Things
But Not for Me
Summertime

编辑:这里是次要问题的次要解决方法:

首先,应该初始化字典,而不是使用 typealias

typealias 只为预先存在的类型创建别名,例如

typealias NumberWithAlotOfDecimals = Double
let a: NumberWithAlotOfDecimals = 10.1
let b: Double = 10.1

ab 都是 Double,因为 NumberWithAlotOfDecimals 只是 Double.

的别名

初始化方法如下:

//typealias tracks = [NSNumber:TrackInfo] // not this
var tracks = [NSNumber:TrackInfo]() // but this

其次,应妥善处理可为空的对象

            if let artistName = song.artist?.name {
                trackInfo.artist = artistName
            }

            if let title = song.album.title {
                trackInfo.album = title
            }
            if let location = song.location {
                trackInfo.location = location
                print("Location: \(location)")
            }

而不是

            if song.artist?.name != nil {
                trackInfo.artist = song.artist?.name as! String
            }

请不要使用 ! 强制解包可为 null 的对象,因为当对象为 nil.

时,这会导致运行时崩溃

最后,这是在Swift中将键值存储到字典中的方法。

            let persistentID = song.persistentID
            //tracks.updateValue(song.persistentID, trackInfo) // not this
            tracks[persistentID] = trackInfo // this