swiftavfoundationprotocolsavmetadataitem

use AVMetadataItem.value to get media title in swift


I want to get the media title through AVMetadataItem class

 /* provides the value of the metadata item */
    @NSCopying public var value: protocol<NSCopying, NSObjectProtocol>? { get }

Above is Apple official illustrate about value property

import Foundation
import AVFoundation
extension AVAsset{
func title() ->String{
    let key = "commonMetadata";

    self.loadValuesAsynchronouslyForKeys([key]){
    if(self.statusOfValueForKey(key, error:nil) == .Loaded)
    {
        let metadata = AVMetadataItem.metadataItemsFromArray(self.metadata, withKey: key, keySpace: AVMetadataKeySpaceCommon)
       if(metadata.count > 0){
        let item = metadata[0];
        return (item.value?.copyWithZone(nil))! as! String;
        }

    }   
};
}
}

then I get error 'Unexpected non-void return value in void function' where I use 'as' perform type casting


Solution

  • The braces that immediately follow loadValuesAsynchronouslyForKeys are a closure, which is the completionHandler parameter to that method. As that method's name suggests, it's an asynchronous operation.

    This means that the closure can't return on behalf of the function you write it in. The closure itself has a void return type, so you can't return a value from it (hence the error message you see).

    It also means that you can't really hide an asynchronous process inside your title() method... at least, not so simply.

    After you call loadValuesAsynchronouslyForKeys, your code after the closure continues running while loadValuesAsynchronouslyForKeys does its thing... When the values are ready (some time later), your closure runs. In this case you have no code after the closure, so your title() method expects to return right after the loadValuesAsynchronouslyForKeys call, except you haven't put a return statement there so you'll get another compile error as soon as you resolve the first one.

    There are some ways to hide something asynchronous inside a synchronous call — for example, you can block, or you can have a return value that says "try again later once I've loaded my value", or you can do it ahead of time so that it's ready when you call the getter... You'll have to plan one that works for you. Or just use asynchronous key-value loading directly.