2015-10-26 96 views
1

如何檢查文件是否是Mac上的別名?這裏是我的代碼到目前爲止:檢查文件是否是別名Swift

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()) 
    } 
} 

如何檢查文件是否和別名?

+0

你是對的。它正在工作,但我會改變這一點。問題仍然是別名 – Silve2611

回答

2

更新:我最初錯誤地認爲,唯一的選擇是使用一個的CoreFoundation(C API)的方法,但實際上並不是真正的(thanks):在基金會(ObjC API)NSURL類並提供一種方法來檢測搜索別名:

// 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>]
下面介紹如何使用基於C-的CoreFoundation API做到這一點:

  • 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 
} 
+0

尼斯解決方案。在我發佈另一個問題之前。我將如何獲取別名指向的文檔的文件路徑? – Silve2611

+0

@ Silve2611:這更涉及到了,所以我建議你提出一個新問題;該文檔中提到「首先使用CFURLCreateBookmarkDataFromFile,然後使用CFURLCreateByResolvingBookmarkData」。一旦你提出了新的問題,如果你仍然需要幫助,請隨時通知我。 – mklement0

+0

好的,我會的。我也做了很大一部分,但我只得到Fileid不是路徑。 – Silve2611

1

有一個簡單的解決方案,它完全地沒有任何指針處理:

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用於符號鏈接,因此您必須確保前者返回,而後者不檢查別名時ES。 如果路徑不存在,函數返回nil。