Проверьте, является ли файл псевдонимом Swift

Как я могу проверить, является ли файл Alias ​​на Mac? Вот мой код до сих пор:

public func getFiles(){
    let folderPath = "/Users/timeBro/Desktop/testfolder"
    let fileManager = NSFileManager.defaultManager()
    let enumerator:NSDirectoryEnumerator = fileManager.enumeratorAtPath(folderPath)!

    for url in enumerator.allObjects {

        let newurl = NSURL(string: url as! String)
        print("\(url as! String)")
        print(url);
        print(newurl?.isFileReferenceURL())
    }
}

Как я могу проверить, является ли файл и псевдоним?

2 ответа

Решение

Обновление: я изначально ошибочно предположил, что единственный вариант - использовать метод CoreFoundation (C API), но на самом деле это не так ( спасибо): класс Foundation (ObjC API) NSURL действительно предоставляет способ обнаружения псевдонимов Finder:

// OSX 10.9+
// Indicates if the specified filesystem path is a Finder alias.
// Returns an optional Boolean: if the lookup failed, such when the path doesn't exist,
// nil is returned.
// Example: isFinderAlias("/path/to/an/alias")
func isFinderAlias(path:String) -> Bool? {
    let aliasUrl = NSURL(fileURLWithPath: path)
    var isAlias:AnyObject? = nil
    do {
        try aliasUrl.getResourceValue(&isAlias, forKey: NSURLIsAliasFileKey)
    } catch _ {}
    return isAlias as! Bool?
}

[Не рекомендуется, кроме как в качестве упражнения в использовании UnsafeMutablePointer<Void> ]
Вот как это сделать с помощью CoreFoundation API на основе C:

  • IsAliasFile() устарел в OS X 10.4,
  • сменил FSIsAliasFile(), который был объявлен устаревшим в 10.8.
  • Текущий метод заключается в использовании CFURLCopyResourcePropertyForKey(), с которым не очень приятно иметь дело в Swift, из-за необходимости использовать ручное управление памятью с UnsafeMutablePointer<Void>,

Надеюсь, я правильно понял управление памятью:

import Foundation

// Indicates if the specified filesystem path is a Finder alias.
// Returns an optional Boolean: if the lookup failed, such when the path
// doesn't exist, nil is returned.
// Example: isFinderAlias("/path/to/an/alias")
func isFinderAlias(path:String) -> Bool? {

    var isAlias:Bool? = nil // Initialize result var.

    // Create a CFURL instance for the given filesystem path.
    // This should never fail, because the existence isn't verified at this point.
    // Note: No need to call CFRelease(fUrl) later, because Swift auto-memory-manages CoreFoundation objects.
    let fUrl = CFURLCreateWithFileSystemPath(nil, path, CFURLPathStyle.CFURLPOSIXPathStyle, false)

    // Allocate void pointer - no need for initialization,
    // it will be assigned to by CFURLCopyResourcePropertyForKey() below.
    let ptrPropVal = UnsafeMutablePointer<Void>.alloc(1)

    // Call the CoreFoundation function that copies the desired information as
    // a CFBoolean to newly allocated memory that prt will point to on return.
    if CFURLCopyResourcePropertyForKey(fUrl, kCFURLIsAliasFileKey, ptrPropVal, nil) {

        // Extract the Bool value from the memory allocated.
        isAlias = UnsafePointer<CFBoolean>(ptrPropVal).memory as Bool

        // Since the CF*() call contains the word "Copy", WE are responsible
        // for destroying (freeing) the memory.
        ptrPropVal.destroy()
    }

    // Deallocate the pointer
    ptrPropVal.dealloc(1)

    return isAlias
}

Существует простое решение, которое полностью обходится без какой-либо обработки указателей:

extension URL {
    func isAlias() -> Bool? {
        let values = try? url.resourceValues(forKeys: [.isSymbolicLinkKey, .isAliasFileKey])
        let alias = values?.isAliasFile
        let symbolic = values?.isSymbolicLink

        guard alias != nil, symbolic != nil else { return nil }
        if alias! && !symbolic! {
            return true
        }
        return false
    }
}

Объяснение: resourceValues(forKeys:) возвращается .isAliasFile а также .isSymbolicLink для символических ссылок, поэтому вы должны убедиться, что первое возвращается, а второе нет при проверке псевдонимов. Если путь не существует, функция возвращает ноль.

Другие вопросы по тегам