【问题标题】:Convert NSSet to Swift Array将 NSSet 转换为 Swift 数组
【发布时间】:2014-08-16 20:27:26
【问题描述】:

在 CoreData 中,我定义了一个 无序 对多关系。这种关系在 Swift 中是这样定义的:

@NSManaged var types : NSMutableSet

但是,为了最好地使用 Swift,我想使用像 Type[] 这样的普通 Swift 数组。然而,CoreData 强迫我使用NS(Mutable)Set。如何将NSSet 类型转换/转换为Array<Type>[]

【问题讨论】:

  • Convert NSArray to Swift array 的可能重复项
  • Type-cast 是不可能的,因为 NSSet 不继承 NSArray,但您可以使用 types.allObjects() 转换为 NSArray
  • @ColinE 它不是重复的,因为您指的是关于 NSArray 而这是关于 NSSet。不同的类型、不同的问题和可能不同的答案。
  • 是的,那是重复的,因为NSSet可以转换为NSArray,从那时起解决方案是相同的。
  • @bouke,Swift 文档中关于 Cocoa 类型的说明如下:Swift 自动在 Array 类型和 NSArray 类之间建立桥梁。(...) 在 Swift 代码中,您可以将 Array 值传递给需要 NSArray 对象的方法。你也可以在桥接类型和对应的类型之间进行转换。,我想这是很明确的说法,来源:developer.apple.com/library/prerelease/mac/documentation/Swift/…,不客气!

标签: core-data swift ios8


【解决方案1】:

感谢@David 的解决方案 我有同样的情况 在我目前的项目中,我们仍然使用 Objective C 和 coredata 模块的快速桥接 所以在我的情况下,我不得不使用以下内容,因为编译器无法干预要转换的通用类型是什么,我必须使用实际传递它:(

extension Set {
    
    func toArray<S>(_ of: S.Type) -> [S] {
        let array = self.map({$0 as! S})
        return array
    }
    
}

并使用:

Items?.toArray(XYZ.self)

在我的托管对象中;变量是这样的供参考

@property (nullable, nonatomic, retain) NSSet<XYZ *> * items;

【讨论】:

    【解决方案2】:

    使用 map 得到这样的数组:

    extension NSSet {
      func toArray<T>() -> [T] {
        let array = self.map({ $0 as! T})
        return array
      }
    }
    
    ...
    let myArray: [MyType] = set.toArray()
    

    【讨论】:

      【解决方案3】:

      这就是我的做法:

      ` let array = object.NSSet?.allObjects as! [ArrayType] `
      

      然后你就可以正常操作数组了:

      for item in array { id = item.id }

      【讨论】:

        【解决方案4】:

        您还可以使用 .sortedArray 对元素进行排序。

        斯威夫特 3:

        yourNSSetType?.sortedArray(using: [NSSortDescriptor(key: "keyToSortBy", ascending: true, selector: #selector(NSNumber.compare(_:)))]) as! [yourNSSetType]
        

        对于字符串,在#selector 调用中使用 NSString.compare。

        【讨论】:

          【解决方案5】:

          从带有 Swift 2.1.1 的 Xcode 7.2 开始

          其实我通过试验发现:

          @NSManaged var types : Set<Type>
          

          工作得很好。

          事实上,CoreData 产生了一些类似的想法:

          @NSManaged var types : NSSet
          

          从编辑器创建NSManagedObject 子类时。所以我想知道是否有一种不是很冗长的方法来使用 filter 方法而不进行强制转换。但是 Swift 应该在 NSSet、NSArray 和它们的对应物之间自动桥接。所以我尝试将它直接声明为 Set 并且它可以工作。

          回答问题,将其转换为数组变得微不足道:

          Array(types)
          

          【讨论】:

          • Core Data 使用 NSSet 来优化底层的东西。即使人体工程学更好,使用 Set 的内存效率可能会更低。
          【解决方案6】:

          从 Xcode 7.2/Swift 2.1 开始,此答案已过时。请参阅接受的答案以获取更新的答案。


          我目前正在使用obj.types.allObjects as Type[],但这感觉像是一种破解/解决方法。

          【讨论】:

          • 没关系,在 Swift 1.2 中将引入原生 Set,因此暂时可以解决问题。
          • 从 Xcode 7 开始,Swift 2。CoreData 仍然使用 NSSet,所以这个 set 直到需要转换为原生 Array 或原生设置.
          • @SwiftArchitect 实际上,从 Xcode 7.2 开始(我还没有尝试过其他版本),如果您直接将其声明为原生 Set,它会起作用,正如我在回答中所解释的那样。
          • 感谢您提供详细信息。 +1。您可能想在回答中具体说明 Xcode 版本。
          【解决方案7】:
          var set = NSSet() //NSSet
          var arr = set.allObjects //Swift Array
          var nsarr = set.allObjects as NSArray  //NSArray
          

          【讨论】:

          • 虽然这个答案仍然有效,但 Swift 1.2 现在还包含一个原生的 Set 结构。 Set 没有allObjects,但支持数组支持的(大多数)操作。所以不需要将 NSSet 转换为数组。
          • 这对我的 collectionview 真的很有帮助——我用它来允许我的 CoreData NSSet 通过 indexpath.row 驱动我的 collectionView
          • 要扩展@bouke 发布的评论,您可以将Swift Set 转换为Array,如let array = Array(mySet)
          猜你喜欢
          • 2021-08-21
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2022-11-27
          • 2018-11-22
          • 1970-01-01
          相关资源
          最近更新 更多