是否可以使用 swift 将 Ipod 库中的音乐保存到我的应用程序中?

Is it possible to save a music from the Ipod library into my app with swift?

当用户 select 从 iPod 库中播放音频时,我有 MPMediaItem 的引用。我正在使用

获取该项目的资产 URL
 let url = item.valueForProperty(MPMediaItemPropertyAssetURL)

但这并没有给我文件的确切物理位置,而是给了我一个 URL w.r.t iPod 库。

ipod-library://item/item.mp3?id=1840064795502796074

有没有办法从 iPod 库中获取歌曲的实体 URL?

编辑 - 实际上我想从物理文件中提取 NSData 并将其发送到我的后端服务器,所以我需要物理文件 URL 而不是相对 URL

MPmediaPickerController 正在工作,我 select 歌曲及其播放但我不想播放 song.I 已尝试将音频文件上传到服务器。我在列表音频中使用 MPMedia Picker 视图,当我要 select 音频时,我将上传到服务器 (HTTP),我该怎么做???如何使用 Swift 代码访问媒体库?

从库中选择歌曲后,将您的 MPMediaItem 对象转换为 NSData 并使用多部分表单数据将其上传到服务器。

将 MPMediaItem 转换为 NSData

-( void)mediaItemToData : (MPMediaItem * ) curItem
{
    NSURL *url = [curItem valueForProperty: MPMediaItemPropertyAssetURL];
    AVURLAsset *songAsset = [AVURLAsset URLAssetWithURL: url options:nil];

    AVAssetExportSession *exporter = [[AVAssetExportSession alloc] initWithAsset: songAsset
                                                                      presetName:AVAssetExportPresetAppleM4A];

    exporter.outputFileType =   @"com.apple.m4a-audio";

    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    NSString * myDocumentsDirectory = ([paths count] > 0) ? [paths objectAtIndex:0] : nil;

    [[NSDate date] timeIntervalSince1970];
    NSTimeInterval seconds = [[NSDate date] timeIntervalSince1970];
    NSString *intervalSeconds = [NSString stringWithFormat:@"%0.0f",seconds];

    NSString * fileName = [NSString stringWithFormat:@"%@.m4a",intervalSeconds];

    NSString *exportFile = [myDocumentsDirectory stringByAppendingPathComponent:fileName];

    NSURL *exportURL = [NSURL fileURLWithPath:exportFile];
    exporter.outputURL = exportURL;

    // do the export
    // (completion handler block omitted)
    [exporter exportAsynchronouslyWithCompletionHandler:
     ^{
         int exportStatus = exporter.status;

         switch (exportStatus)
         {
             case AVAssetExportSessionStatusFailed:
             {
                 NSError *exportError = exporter.error;
                 NSLog (@"AVAssetExportSessionStatusFailed: %@", exportError);
                 break;
             }
             case AVAssetExportSessionStatusCompleted:
             {
                 NSLog (@"AVAssetExportSessionStatusCompleted");

                 NSData *data = [NSData dataWithContentsOfFile: [myDocumentsDirectory
                                                                 stringByAppendingPathComponent:fileName]];

                 [arrayMusic addObject:data];
                 data = nil;

                 break;
             }
             case AVAssetExportSessionStatusUnknown:
             {
                 NSLog (@"AVAssetExportSessionStatusUnknown"); break;
             }
             case AVAssetExportSessionStatusExporting:
             {
                 NSLog (@"AVAssetExportSessionStatusExporting"); break;
             }
             case AVAssetExportSessionStatusCancelled:
             {
                 NSLog (@"AVAssetExportSessionStatusCancelled"); break;
             }
             case AVAssetExportSessionStatusWaiting:
             {
                 NSLog (@"AVAssetExportSessionStatusWaiting"); break;
             }
             default:
             {
                 NSLog (@"didn't get export status"); break;
             }
         }
     }];

}

改编 Krishna 的答案,它使用 AVAssetExportSessionMPMediaItem 保存到文件中,您可以在 Swift 3:

中执行类似以下操作
/// Export MPMediaItem to temporary file.
///
/// - Parameters:
///   - assetURL: The `assetURL` of the `MPMediaItem`.
///   - completionHandler: Closure to be called when the export is done. The parameters are a boolean `success`, the `URL` of the temporary file, and an optional `Error` if there was any problem. The parameters of the closure are:
///
///   - fileURL: The `URL` of the temporary file created for the exported results.
///   - error: The `Error`, if any, of the asynchronous export process.

func export(_ assetURL: URL, completionHandler: @escaping (_ fileURL: URL?, _ error: Error?) -> ()) {
    let asset = AVURLAsset(url: assetURL)
    guard let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else {
        completionHandler(nil, ExportError.unableToCreateExporter)
        return
    }

    let fileURL = URL(fileURLWithPath: NSTemporaryDirectory())
        .appendingPathComponent(NSUUID().uuidString)
        .appendingPathExtension("m4a")

    exporter.outputURL = fileURL
    exporter.outputFileType = "com.apple.m4a-audio"

    exporter.exportAsynchronously {
        if exporter.status == .completed {
            completionHandler(fileURL, nil)
        } else {
            completionHandler(nil, exporter.error)
        }
    }
}

func exampleUsage(with mediaItem: MPMediaItem) {
    if let assetURL = mediaItem.assetURL {
        export(assetURL) { fileURL, error in
            guard let fileURL = fileURL, error == nil else {
                print("export failed: \(error)")
                return
            }

            // use fileURL of temporary file here
            print("\(fileURL)")
        }
    }
}

enum ExportError: Error {
    case unableToCreateExporter
}

或者,在 Swift 2:

/// Export MPMediaItem to temporary file.
///
/// - Parameters:
///   - assetURL: The `assetURL` of the `MPMediaItem`.
///   - completionHandler: Closure to be called when the export is done. The parameters are a boolean `success`, the `URL` of the temporary file, and an optional `Error` if there was any problem. The parameters of the closure are:
///
///   - fileURL: The `URL` of the temporary file created for the exported results.
///   - error: The `Error`, if any, of the asynchronous export process.

func export(assetURL: NSURL, completionHandler: (NSURL?, ErrorType?) -> ()) {
    let asset = AVURLAsset(URL: assetURL)
    guard let exporter = AVAssetExportSession(asset: asset, presetName: AVAssetExportPresetAppleM4A) else {
        completionHandler(nil, ExportError.unableToCreateExporter)
        return
    }

    let fileURL = NSURL(fileURLWithPath: NSTemporaryDirectory())
        .URLByAppendingPathComponent(NSUUID().UUIDString)!
        .URLByAppendingPathExtension("m4a")

    exporter.outputURL = fileURL
    exporter.outputFileType = "com.apple.m4a-audio"

    exporter.exportAsynchronouslyWithCompletionHandler {
        if exporter.status == .Completed {
            completionHandler(fileURL, nil)
        } else {
            completionHandler(nil, exporter.error)
        }
    }
}

func exampleUsage(with mediaItem: MPMediaItem) {
    if let assetURL = mediaItem.assetURL {
        export(assetURL) { fileURL, error in
            guard let fileURL = fileURL where error == nil else {
                print("export failed: \(error)")
                return
            }

            // use fileURL of temporary file here
            print("\(fileURL)")
        }
    }
}

enum ExportError: ErrorType {
    case unableToCreateExporter
}

如您所见,我把它放在了一个临时文件夹中,而不是 Documents 文件夹中。此外,我使用 UUID 而不是自某个参考日期以来的秒数来生成临时文件。不过思路基本一样