swift - Swift - 如何使用类类型作为参数/变量
问题描述
我正在尝试创建一个有点通用的函数来根据属性的值对文件 URL 进行排序
我的目标是:
1) 将 URL 和一些参数(包括类型)传递给函数。然后将遍历文件的属性
2) 将匹配的文件属性和 URL 添加到元组数组中
3) 根据找到的属性值对元组进行排序
4)返回排序后的数组并按排序顺序显示项目
我相信我需要将属性的类型传递给排序函数,以便我能够在元组中设置它,因为我无法使用“Any”进行排序,但我不确定该怎么做
我可以将任何内容传递给排序函数并在排序函数中构造或解构我需要的值,因为这将根据用户选择的操作进行预定义
//Initial implementation to be later tied to IBActions and simplified
func sortFiles(sortByKeyString : String, fileURLArray : [URL]) -> [URL]
{
switch sortByKeyString {
case "date-created-DESC":
let fileAttributeKeyString : String = "creationDate"
let isSortOrderDesc = true
let objectTypeString : String = NSDate.className()
let sortedFileURLArray = sortFileArrayByType(fileAttributeKeyString: fileAttributeKeyString, fileURLArray: fileURLArray, type: objectTypeString, isSortOrderDesc : isSortOrderDesc)
return sortedFileURLArray
default:
return fileURLArray
}
}
//Generic function to get a files attributes from a URL by requested
type
func sortFileArrayByType(fileAttributeKeyString : String, fileURLArray : [URL], type: String, isSortOrderDesc : Bool) -> [URL] {
let fileManager = FileManager.default
let attributeToLookFor : FileAttributeKey = FileAttributeKey.init(rawValue: fileAttributeKeyString)
var tupleArrayWithURLandAttribute : [(url: URL, attribute: *Any*)]? = nil
for url in fileURLArray {
do {
let attributes = try fileManager.attributesOfItem(atPath: url.path)
for (key, value) in attributes {
if key.rawValue == fileAttributeKeyString {
tupleArrayWithURLandAttribute?.append((url: url, attribute: value))
}
}
let sortedTupleArrayWithURLandAttribute = tupleArrayWithURLandAttribute?.sorted(by: { $0.attribute < $1.attribute)})
// Need to Sort dictionary into array
return sortedTupleArrayWithURLandAttribute
} catch {
return fileURLArray
}
}
}
解决方案
首先阅读The Swift Programming Language中的Metatype Type。阅读后继续回答。
从中您已经了解到,您可以将函数参数的类型声明为类型的类型(您可以交叉眼),AKA metatype,因此可以将类型传递给函数。将其与泛型和 Swift 的类型推断相结合,您可以将函数声明为:
func sortFileArrayByType<T>(fileAttributeKeyString : String,
attributeType : T.Type,
fileURLArray : [URL]
) -> [(url: URL, attribute: T)]
where T : Comparable
这将添加attributeType
类型为 where 的元类型T
的参数T
将被推断。例如,String.self
可以传递元类型T
并将被推断为String
.
该where
子句进行了限制T
,因此只有Comparable
允许的类型,这是启用函数进行排序所必需的。文件属性可以是Date
,String
和NSNumber
值; 不幸的是后者不符合,Comparable
所以你需要添加一个扩展来实现它,以下就足够了:
extension NSNumber : Comparable
{
public static func <(a : NSNumber, b : NSNumber) -> Bool { return a.compare(b) == .orderedAscending }
public static func ==(a : NSNumber, b : NSNumber) -> Bool { return a.compare(b) == .orderedSame }
}
在函数体中,您需要将元组数组声明为具有 type 属性T
:
var tupleArrayWithURLandAttribute : [(url: URL, attribute: T)] = []
当您添加条目时,您需要将返回的值attributesOfItem
转换为T
:
tupleArrayWithURLandAttribute.append((url: url, attribute: value as! T))
请注意as!
这里的使用,您必须在函数调用中正确匹配属性名称及其值的类型,否则您将获得运行时中止。如果需要,将其作为软错误处理,留作练习。
您发布的代码中有许多拼写错误等,它们留给您修复,您的功能应该可以工作。调用可能如下所示:
let ans = sortFileArrayByType2(fileAttributeKeyString: "NSFileCreationDate",
attributeType: Date.self,
fileURLArray: urlArray)
在这种情况下的类型ans
将是[(url: URL, attribute: Date)]
高温高压
推荐阅读
- php - 页面重定向问题codeigniter:404错误
- css - 标题 div 的背景颜色不起作用
- pulumi - 创建注册表后如何将 docker 映像推送到 ECR?
- java - Switch Case 语句或其替代 If Condition 在 android 中不起作用
- android - 谷歌警告开发者为 Android 应用程序包含 64 位版本
- java - 我的 switch 语句没有返回任何东西?
- angular - 如何为两个单词标题中的单个单词赋予单独的颜色
- asp.net - ASP Webservice 可执行即服务 (SOAP)
- javascript - 我的 AJAX POST 中的 500(内部服务器错误)
- python-2.7 - 尝试通过 Python 2.7 和 ctds 连接到 Azure 数据仓库时出现 _tds.InterfaceError