Ron Pelayo
Ron Pelayo

Reputation: 655

Cannot convert value of type to expected argument type

So I'm converting this line of code

 NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(TidyFeed * _Nonnull item, NSDictionary<NSString *,id> * _Nullable bindings) {
        return ![item.feedEntryId isEqualToString:feedEntryId];
    }];

to swift code

var predicate = NSPredicate { (item: TidyFeed, bindings: NSDictionary) in
        return !(item.feedEntryId == feedEntryId)
    }

but I get this error

Cannot convert value of type '(TidyFeed, NSDictionary) -> Bool' to expected argument type '(AnyObject, [String : AnyObject]?) -> Bool'

has anyone encounter this error when using blocks?

Additional Info

Swift code

  apiClient.dismissFeed(feedEntryId, completion: {(responseObject: AnyObject, error: NSError) -> Void in

    })

Error

Cannot convert value of type '(AnyObject, NSError) -> Void' to expected argument type 'AFAPIOperationCompletionBlock!'

and here's the completion block code of AFAPIOperationCompletionBlock

- (void) completion:(id)responseObject error:(NSError *)error 

Upvotes: 1

Views: 4258

Answers (1)

Martin R
Martin R

Reputation: 540075

In Objective-C, the first parameter id evaluatedBlock of the closure can be substituted by any object pointer, like TidyFeed *, and that is a known method to avoid additional pointer conversion if you know for sure that the evaluated objects are in fact of that type.

Swift however does not allow this, and you have to cast the pointer inside the block:

let predicate = NSPredicate { (item: AnyObject, _) -> Bool in
    return (item as! TidyFeed).feedEntryId != feedEntryId
}

This will crash if the block is called with an object which is not of the type TidyFeed. A safe version is

let predicate = NSPredicate { (item: AnyObject, _) -> Bool in
    if let feed = item as? TidyFeed {
        return feed.feedEntryId != feedEntryId
    } else {
        return false
    }
}

with an optional cast. This can be written more compactly as:

let predicate = NSPredicate { (item: AnyObject, _) -> Bool in
    return (item as? TidyFeed)?.feedEntryId != feedEntryId
}

Note also how you can use the wildcard pattern _ for the unused bindings parameter.

Upvotes: 0

Related Questions