FS.O6 FS.O6 - 3 months ago 23
iOS Question

Remove a custom object from an array (Swift)

I have an array called

remindersArray
that contains a custom object called
Reminder
(each
Reminder
object has
title
and
identifier
).

Inside
Reminder
I have a static fun called
removeReminderWithIdentifier
that should find the reminder and delete it from the array.

I've tried to do it like this:

static func removeReminderWithIdentifier(reminderIdentifier: String) {
for currentReminder in Reminder.remindersArray {
if currentReminder.identifier == reminderIdentifier {
Reminder.remindersArray.removeAtIndex(Reminder.remindersArray.indexOf(currentReminder)) //Compile error
}
}
}


but it gives me this compile error:

Cannot convert value of type 'Reminder' to expected argument type '@noescape (Reminder) throws -> Bool'


Any idea how can I remove that object with this identifier from the array?

Thanks!

Answer

See the header of two indexOf(_:) methods for CollectionType:

extension CollectionType where Generator.Element : Equatable {
    /// Returns the first index where `value` appears in `self` or `nil` if
    /// `value` is not found.
    ///
    /// - Complexity: O(`self.count`).
    @warn_unused_result
    public func indexOf(element: Self.Generator.Element) -> Self.Index?
}

extension CollectionType {
    /// Returns the first index where `predicate` returns `true` for the
    /// corresponding value, or `nil` if such value is not found.
    ///
    /// - Complexity: O(`self.count`).
    @warn_unused_result
    public func indexOf(@noescape predicate: (Self.Generator.Element) throws -> Bool) rethrows -> Self.Index?
}

If you want to use the first indexOf(_:) (which you are trying in your code), the element type needs to be Equatable. When your Reminder class does not conform to Equatable, Swift ignores the first indexOf(_:), so the second can be the only candidate, having @noescape (Self.Generator.Element) throws -> Bool as its only argument. In your case Self.Generator.Element is Reminder.

So, one way to avoid this error is making your Reminder conform to Equatable.

extension Reminder: Equatable {}
func == (lhs: Reminder, rhs: Reminder) -> Bool {
    return lhs.identifier == rhs.identifier /* && ... you may need more complex condition. */
    /* return lhs === rhs //or simple use `===`. */
}

But you have some options to do it:

If your reminderArray contains just one element for each unique identifier, you can write something like this, without making your Reminder Equatable:

static func removeReminderWithIdentifier(reminderIdentifier: String) {
    if let index = Reminder.remindersArray.indexOf({$0.identifier == reminderIdentifier}) {
        Reminder.remindersArray.removeAtIndex(index)
    }
}

If your remindersArray may contain multiple Reminder instances having the same identifier, this should work:

static func removeReminderWithIdentifier3(reminderIdentifier: String) {
    Reminder.remindersArray = Reminder.remindersArray.filter{$0.identifier != reminderIdentifier}
}

Choose one (or more?) and make it a try.

Comments