After Swift 3 conversion, I can't get rid of error: “Ambiguous use of 'indexOfObject(passingTest:)'”

别来无恙 提交于 2019-12-12 10:48:11

问题


I'm using NSArray's indexesOfObjects(passingTest:), but after I converted my code to Swift 3 I get the error: "Ambiguous use of 'indexOfObject(passingTest:)'". My code below worked fine with Swift 2.3.

let indexesOfBubbleConstraints = bubbleConstraints.indexesOfObjects(passingTest: { (constraint, idx, stop) in
        if let view = constraint.firstItem as? UIView{
            return view.tag == usernameTag
        }
        else{
            return false
        }
    })

For Swift 3, I also had to cast constraint to AnyObject, but that doesn't fix the actual problem.

I ended up using func indexesOfObjects(options: NSEnumerationOptions = [], passingTest: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Bool) with an empty Array for options as below. This works, but I still don't understand why I'm getting the "Ambiguous..." error with my original implementation.

let indexesOfBubbleConstraints = bubbleConstraints.indexesOfObjects(options: [], passingTest: { (constraint, idx, stop) in
        if let view = (constraint as AnyObject).firstItem as? UIView{
            return view.tag == usernameTag
        }
        else{
            return false
        }
    })

回答1:


In Objective-C, the two indexesOf methods are distinct two methods:

- (NSIndexSet *)indexesOfObjectsPassingTest:(BOOL (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))predicate NS_AVAILABLE(10_6, 4_0);
- (NSIndexSet *)indexesOfObjectsWithOptions:(NSEnumerationOptions)opts passingTest:(BOOL (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))predicate NS_AVAILABLE(10_6, 4_0);

And now, Swift 3 import those as ambiguous two methods:

@available(iOS 4.0, *)
open func indexesOfObjects(passingTest predicate: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Bool) -> IndexSet

@available(iOS 4.0, *)
open func indexesOfObjects(options opts: NSEnumerationOptions = [], passingTest predicate: (Any, Int, UnsafeMutablePointer<ObjCBool>) -> Bool) -> IndexSet

One is indexesOfObjects(passingTest:), and another is indexesOfObjects(options:passingTest:). And unfortunately, Swift 3 has given a default value for the parameter options, which has made a simple call like bubbleConstraints.indexesOfObjects(passingTest: ...) ambiguous.

It may be calling

  • indexesOfObjects(passingTest:)

or

  • indexesOfObjects(options:passingTest:) with giving default value to options

(Swift should not give a default value, if it causes this sort of ambiguity. Better send a bug report.)

In this case, your workaround code, using indexesOfObjects(options:passingTest:) should work, but there is another work around:

bubbleConstraints.indexesOfObjects(passingTest:) {constraint, idx, stop in
    //...
}

The method reference .indexesOfObjects(passingTest:) returns the method indexesOfObjects(passingTest:) as a closure, and the above expression is calling it.


By the way, you better consider using Swift's collection methods, rather than using an NSArrays method:

let indexesOfBubbleConstraints = bubbleConstraints.enumerated().lazy
    .filter {(idx, constraint) in
        //...
    }.map{$0.offset}


来源:https://stackoverflow.com/questions/39569250/after-swift-3-conversion-i-cant-get-rid-of-error-ambiguous-use-of-indexofob

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!