ios 我如何做 indexOfObject 或适当的 containsObject
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/24010700/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do I do indexOfObject or a proper containsObject
提问by Daij-Djan
With an array: How do I do indexOfObject
or a proper containsObject
?
使用数组:我该怎么做indexOfObject
或正确containsObject
?
I mean I know I could just bridge the Array to NSArray
and do it there ^^
But there must be a 'native' way of doing this
我的意思是我知道我可以将 Array 桥接到NSArray
那里并在那里做 ^^
但必须有一种“本地”的方式来做到这一点
P.S. for the containsObject
I guess I could filter the array too but for indexOf?
PScontainsObject
我想我也可以过滤数组但对于indexOf?
回答by matt
You can use the built-in find
, and thus avoid bridging to Objective-C — but only if your element type is Equatable. (If it isn't Equatable, you can make it so with a comparison function and an extension.)
您可以使用内置的find
,从而避免桥接到 Objective-C — 但前提是您的元素类型是Equatable。(如果它不是 Equatable,您可以使用比较函数和扩展来实现。)
Example:
例子:
func == (lhs:Piece,rhs:Piece) -> Bool {
return lhs.val == rhs.val
}
class Piece:Equatable,Printable {
var val : Int
var description : String { return String(val) }
init (_ v:Int) {
val = v
}
}
Now you can call find(arr,p)
where arr
is an Array<Piece>
and p
is a Piece
.
现在您可以调用find(arr,p)
where arr
is anArray<Piece>
和p
is a Piece
。
Once you have this, you can develop utilities based on it. For example, here's a global function to remove an object from an array without bridging to Objective-C:
一旦你有了它,你就可以基于它开发实用程序。例如,这里有一个全局函数,用于从数组中删除一个对象,而无需桥接到 Objective-C:
func removeObject<T:Equatable>(inout arr:Array<T>, object:T) -> T? {
if let found = find(arr,object) {
return arr.removeAtIndex(found)
}
return nil
}
And test it like this:
并像这样测试它:
var arr = [Piece(1), Piece(2), Piece(3)]
removeObject(&arr,Piece(2))
println(arr)
You can do this for NSObject subclasses too. Example:
您也可以对 NSObject 子类执行此操作。例子:
func == (v1:UIView, v2:UIView) -> Bool {
return v1.isEqual(v2)
}
extension UIView : Equatable {}
Now you can call find
on an Array of UIView. It's sort of a pain in the butt, though, having to do this for every single class where you want to be able to use find
on an Array of that class. I have filed an enhancement request with Apple requesting that all NSObject subclasses be considered Equatable and that ==
should fall back on isEqual:
automatically.
现在你可以调用find
一个 UIView 数组。但是,这有点麻烦,必须为每个您希望能够find
在该类的 Array 上使用的类执行此操作。我已经向 Apple 提交了一份增强请求,要求将所有 NSObject 子类视为 Equatable 并且==
应该isEqual:
自动回退。
EDITStarting in Seed 3, this isautomatic for UIView and other NSObject classes. So find
now just works for them.
编辑从种子 3 开始,这是UIView 和其他 NSObject 类自动的。所以find
现在只为他们工作。
EDIT 2Starting in Swift 2.0, indexOf
will exist as a method:
编辑 2从 Swift 2.0 开始,indexOf
将作为一种方法存在:
let s = ["Manny", "Moe", "Hyman"]
let ix = s.indexOf("Moe") // 1
Alternatively, it takes a function that returns Bool:
或者,它需要一个返回 Bool 的函数:
let ix2 = s.indexOf {extension RangeReplaceableCollectionType where Generator.Element : Equatable {
mutating func removeObject(object:Self.Generator.Element) {
if let found = self.indexOf(object) {
self.removeAtIndex(found)
}
}
}
.hasPrefix("J")} // 2
Again, this works only on collections of Equatable, since obviously you cannot locate a needle in a haystack unless you have a way of identifying a needle when you come to it.
同样,这仅适用于 Equatable 的集合,因为显然你无法在大海捞针中找到针,除非你有办法识别针。
EDIT 3Swift 2.0 also introduces protocol extensions. This means I can rewrite my global function removeObject
as a method!
编辑 3Swift 2.0 还引入了协议扩展。这意味着我可以将全局函数重写removeObject
为方法!
For example:
例如:
var arr = [Piece(1), Piece(2), Piece(3)]
arr.removeObject(Piece(2))
Since Array adopts RangeReplaceableCollectionType, now I can write code like this:
由于Array采用了RangeReplaceableCollectionType,现在我可以这样写代码:
import Foundation
extension Array {
func contains(object:AnyObject!) -> Bool {
if(self.isEmpty) {
return false
}
let array: NSArray = self.bridgeToObjectiveC();
return array.containsObject(object)
}
func indexOf(object:AnyObject!) -> Int? {
var index = NSNotFound
if(!self.isEmpty) {
let array: NSArray = self.bridgeToObjectiveC();
index = array.indexOfObject(object)
}
if(index == NSNotFound) {
return Optional.None;
}
return index
}
//#pragma mark KVC
func getKeyPath(keyPath: String!) -> AnyObject! {
return self.bridgeToObjectiveC().valueForKeyPath(keyPath);
}
}
Oh, happy day!
哦,快乐的一天!
回答by Maximilian Litteral
Its actually able to be done in Swift. To get the index use find(YourArray, ObjectToFind)
它实际上可以在 Swift 中完成。获取索引使用find(YourArray, ObjectToFind)
回答by Daij-Djan
As I was told, this isn't available yet / I have to bridge it to NSArray
有人告诉我,这还不可用/我必须将它桥接到 NSArray
I don't like this and it feels dirty so I went and did this in an extension. that way it hides the usage of NSArray and allows apple to provide it later
我不喜欢这个,而且感觉很脏,所以我在扩展中做了这个。这样它就隐藏了 NSArray 的使用,并允许苹果稍后提供它
func findIndex<T: Equatable>(array: [T], valueToFind: T) -> Int? {
for (index, value) in enumerate(array) {
if value == valueToFind {
return index
}
}
return nil
}
回答by Max MacLeod
Apple provide an example of exactly this in the The Swift Programming Languagebook. Specifically, see the section on Type Constraints in Action (p621 in the iBook).
Apple 在The Swift Programming Language一书中提供了一个例子。具体来说,请参阅“类型约束在行动”部分(iBook 中的 p621)。
haystack.filter({let fruits: NSArray = [ "apple", "orange", "tomato (really?)" ]
let index = fruits.indexOfObject("orange")
println("Index of Orange: \(index)")
== needle}).count > 0
Everything depends upon your type implementing Equatable.
一切都取决于您实现Equatable的类型。
The Swift Programming Language covers that and explains how to implement that protocol:
Swift Programming Language 涵盖了这一点并解释了如何实现该协议:
“The Swift standard library defines a protocol called Equatable, which requires any conforming type to implement the equal to operator (==) and the not equal to operator (!=) to compare any two values of that type. ”
“Swift 标准库定义了一个名为 Equatable 的协议,它要求任何符合的类型实现等于运算符 (==) 和不等于运算符 (!=) 来比较该类型的任何两个值。”
NSHipsterhas a couple of relevant posts on this subject:
NSHipster有几个关于这个主题的相关帖子:
Swift Default Protocol ImplementationsSwift Comparison Protocols
I also found this answer very useful in implementing Equatable:
我还发现这个答案在实现 Equatable 时非常有用:
How do I implement Swift's Comparable protocol?
Alhough it mentions Comparable, Equatable is a subset and the explanation is good.
虽然它提到了 Comparable,但 Equatable 是一个子集,解释很好。
Excerpts above from: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/gb/jEUH0.l
以上摘录自:Apple Inc. “The Swift Programming Language”。电子书。https://itun.es/gb/jEUH0.l
回答by rmooney
One other option is to use filter:
另一种选择是使用过滤器:
func findObject<C: CollectionType where C.Generator.Element: AnyObject>(domain: C, value: C.Generator.Element) -> Int? {
for (index, element) in enumerate(domain) {
if element === value {
return index
}
}
return nil
}
This checks to see if array haystack contains object needle.
这会检查数组 haystack 是否包含对象 Needle。
回答by Leandros
You can't. That's why NSArray
is still there. However, the Apple documentation reads as follows about String
and NSString
:
你不能。这就是为什么NSArray
仍然存在。但是,Apple 文档中关于String
和的内容如下NSString
:
Swift's String type is bridged seamlessly to Foundation's NSString class. If you are working with the Foundation framework in Cocoa or Cocoa Touch, the entire NSString API is available to call on any String value you create, in addition to the String features described in this chapter. You can also use a String value with any API that requires an NSString instance.
Swift 的 String 类型无缝桥接到 Foundation 的 NSString 类。如果您在 Cocoa 或 Cocoa Touch 中使用 Foundation 框架,那么除了本章中描述的 String 功能之外,整个 NSString API 都可用于调用您创建的任何 String 值。您还可以将 String 值用于任何需要 NSString 实例的 API。
Following that approach, the NSArray
API shouldbe available on Array
, but it isn't because the native Swift Array
is a primitive (most likely a struct or similar), so you have to "convert"it to an NSArray
.
按照这种方法,NSArray
API应该在 上可用Array
,但这不是因为本机 SwiftArray
是原始类型(很可能是结构或类似的),因此您必须将其“转换”为NSArray
.
回答by Ben Gottlieb
It appears that not all of the toll-free bridging from NS/CF space is in place. However, if you declare your array as an NSArray, it works fine:
似乎并非所有来自 NS/CF 空间的免费桥接都到位。但是,如果您将数组声明为 NSArray,则它可以正常工作:
##代码##回答by phatmann
If your array elements are objects and you want to find an identical object in that array, you can use this function:
如果您的数组元素是对象并且您想在该数组中找到相同的对象,则可以使用此函数:
##代码##