如何知道用户是否可以在swift中读取目录的内容

时间:2016-11-13 20:52:52

标签: swift

为了避免已知错误,我需要在枚举目录之前kwnow,如果用户可以读取它。

我如何在swift(最新版本,使用Xcode和MAC OS最新版本)中做到这一点?

更多信息: 尝试在swift中枚举目录可能会导致应用程序崩溃,如果用户无法访问它。没有办法捕获错误以防止崩溃,但只有在用户无法访问目录时才会发生。因此,事先知道是否可以读取目录(因此枚举)将有助于防止崩溃。

可兑现代码:

有一个例子: Timothy Wood报道的https://bugs.swift.org/browse/SR-2872

此示例: Jean Suisse

报告的http://prod.lists.apple.com/archives/cocoa-dev/2016/Oct/msg00166.html

1 个答案:

答案 0 :(得分:1)

Xcode 8.1的release notes中提供了此错误的解决方法。引用发行说明:

  

SDK中的某些Objective-C方法可能会错误地注释或   假设类型为nonnull而不是nullable。 Swift的一种类型   视为结构,例如NSURLFoundation.URL)或NSDate   (Foundation.Date)导致具有名称的方法中的运行时崩溃   像bridgeFromObjectiveC;在其他情况下,它可能导致崩溃或   用户代码中的未定义行为。如果你确定了这种方法,请   在bugreport.apple.com上提交报告。作为解决方法,添加一个   Objective-C中的蹦床功能具有正确的可空性   注释。例如,以下功能将允许您   呼叫   FileManager' enumerator(at:includingPropertiesForKeys:options:errorHandler:)   带有错误处理程序的方法,该处理程序接受nil个网址:

static inline NSDirectoryEnumerator<NSURL *> * _Nullable
fileManagerEnumeratorAtURL(NSFileManager *fileManager, NSURL * _Nonnull url, NSArray<NSURLResourceKey> * _Nullable keys, NSDirectoryEnumerationOptions options, BOOL (^ _Nullable errorHandler)(NSURL * _Nullable errorURL, NSError * _Nonnull error)) {
     return [fileManager enumeratorAtURL:url includingPropertiesForKeys:keys options:options errorHandler:^(NSURL * _Nonnull errorURL, NSError * _Nonnull error) {
      return errorHandler(errorURL, error);
   }];
}
  

此功能可以包含在您的桥接标题中(适用于应用或   测试目标)或伞头(用于框架目标)。 (27749845)

采取的步骤:

1)将新的.m文件添加到名为DirectoryEnumeratorGlue.m的项目中。当你添加它时,Xcode会问你是否希望它为你创建一个桥接标题,说是。将以下内容放在DirectoryEnumeratorGlue.m中:

NSDirectoryEnumerator<NSURL *> * _Nullable
fileManagerEnumeratorAtURL(NSFileManager * _Nonnull fileManager, NSURL * _Nonnull url, NSArray<NSURLResourceKey> * _Nullable keys, NSDirectoryEnumerationOptions options, BOOL (^ _Nullable errorHandler)(NSURL * _Nullable errorURL, NSError * _Nonnull error)) {
     return [fileManager enumeratorAtURL:url includingPropertiesForKeys:keys options:options errorHandler:^(NSURL * _Nonnull errorURL, NSError * _Nonnull error) {
      return errorHandler(errorURL, error);
   }];
}

2)将新的.h文件添加到项目中,名为DirectoryEnumeratorGlue.h。将以下内容放在DirectoryEnumeratorGlue.h中:

extern NSDirectoryEnumerator<NSURL *> * _Nullable
fileManagerEnumeratorAtURL(NSFileManager * _Nonnull fileManager, NSURL * _Nonnull url, NSArray<NSURLResourceKey> * _Nullable keys, NSDirectoryEnumerationOptions options, BOOL (^ _Nullable errorHandler)(NSURL * _Nullable errorURL, NSError * _Nonnull error));

3)将以下内容添加到您的桥接标题中:

#import <Foundation/Foundation.h>
#import "DirectoryEnumeratorGlue.h"

4)用你喜欢的方式替换你在Swift调用中对FileManager.default.enumerator的调用:

    let enumerator = fileManagerEnumeratorAtURL(FileManager.default, url, [],  [], {
        (errorURL, error) in
        return true
    })