在 Swift 3中从数组中移除对象

在我的应用程序中,当选择单元格时我在数组中添加了一个对象,当重新选择单元格时取消选择并删除对象。我用了那个代码,但给我错误。

extension Array {
func indexOfObject(object : AnyObject) -> NSInteger {
return (self as NSArray).indexOfObject(object)
}


mutating func removeObject(object : AnyObject) {
for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) {
self.removeAtIndex(index)
}
}
}


class MyViewController: UITableViewController {
var arrContacts: [Any] = []
var contacts: [Any] = []


func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
arrContacts.removeObject(contacts[indexPath.row])
}
}

它给了我两个这样的错误:

C-style for statement has been removed in Swift 3
Value of type '[Any]' has no member 'removeObject'
125080 次浏览

Try this in Swift 3

array.remove(at: Index)

Instead of

array.removeAtIndex(index)

Update

"Declaration is only valid at file scope".

Make sure the object is in scope. You can give scope "internal", which is default.

index(of:<Object>) to work, class should conform to Equatable

The Swift equivalent to NSMutableArray's removeObject is:

var array = ["alpha", "beta", "gamma"]


if let index = array.firstIndex(of: "beta") {
array.remove(at: index)
}

if the objects are unique. There is no need at all to cast to NSArray and use indexOfObject:

The API index(of: also works but this causes an unnecessary implicit bridge cast to NSArray.

Of course you can write an extension of RangeReplaceableCollection to emulate the function. But due to value semantics you cannot name it removeObject.

extension RangeReplaceableCollection where Element : Equatable {
@discardableResult
mutating func remove(_ element : Element) -> Element?
{
if let index = firstIndex(of: element) {
return remove(at: index)
}
return nil
}
}

Like remove(at: it returns the removed item or nil if the array doesn't contain the item.


If there are multiple occurrences of the same object use filter. However in cases like data source arrays where an index is associated with a particular object firstIndex(of is preferable because it's faster than filter.

Update:

In Swift 4.2+ you can remove one or multiple occurrences of beta with removeAll(where:):

array.removeAll{$0 == "beta"}
  1. for var index = self.indexOfObject(object); index != NSNotFound; index = self.indexOfObject(object) is for loop in C-style and has been removed

  2. Change your code to something like this to remove all similar object if it have looped:

    let indexes = arrContacts.enumerated().filter { $0.element == contacts[indexPath.row] }.map{ $0.offset }
    for index in indexes.reversed() {
    arrContacts.remove(at: index)
    }
    

The correct and working one-line solution for deleting a unique object (named "objectToRemove") from an array of these objects (named "array") in Swift 3 is:

if let index = array.enumerated().filter( { $0.element === objectToRemove }).map({ $0.offset }).first {
array.remove(at: index)
}

Another nice and useful solution is to create this kind of extension:

extension Array where Element: Equatable {


@discardableResult mutating func remove(object: Element) -> Bool {
if let index = index(of: object) {
self.remove(at: index)
return true
}
return false
}


@discardableResult mutating func remove(where predicate: (Array.Iterator.Element) -> Bool) -> Bool {
if let index = self.index(where: { (element) -> Bool in
return predicate(element)
}) {
self.remove(at: index)
return true
}
return false
}


}

In this way, if you have your array with custom objects:

let obj1 = MyObject(id: 1)
let obj2 = MyObject(id: 2)
var array: [MyObject] = [obj1, obj2]


array.remove(where: { (obj) -> Bool in
return obj.id == 1
})
// OR
array.remove(object: obj2)
var a = ["one", "two", "three", "four", "five"]


// Remove/filter item with value 'three'
a = a.filter { $0 != "three" }

For Swift 3, you can use index(where:) and include a closure that does the comparison of an object in the array ($0) with whatever you are looking for.

var array = ["alpha", "beta", "gamma"]
if let index = array.index(where: {$0 == "beta"}) {
array.remove(at: index)
}

Swift 4

var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]


if let index = students.firstIndex(where: { $0.hasPrefix("A") }) {
students.remove(at: index)
}

In Swift 5, Use this Extension:

extension Array where Element: Equatable{
mutating func remove (element: Element) {
if let i = self.firstIndex(of: element) {
self.remove(at: i)
}
}
}

example:

var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")

In Swift 3, Use this Extension:

extension Array where Element: Equatable{
mutating func remove (element: Element) {
if let i = self.index(of: element) {
self.remove(at: i)
}
}
}

example:

var array = ["alpha", "beta", "gamma"]
array.remove(element: "beta")

Extension for array to do it easily and allow chaining for Swift 4.2 and up:

public extension Array where Element: Equatable {
@discardableResult
public mutating func remove(_ item: Element) -> Array {
if let index = firstIndex(where: { item == $0 }) {
remove(at: index)
}
return self
}


@discardableResult
public mutating func removeAll(_ item: Element) -> Array {
removeAll(where: { item == $0 })
return self
}
}

Remove object from array

In Swift 3 and Swift 4

var array = ["a", "b", "c", "d", "e", "f"]


for (index, element) in array.enumerated().reversed() {
array.remove(at: index)
}

From Swift 4.2 you can use more advanced approach(faster and memory efficient)

array.removeAll(where: { $0 == "c" })

instead of

array = array.filter { !$0.hasPrefix("c") }

Read more here

This is official answer to find index of specific object, then you can easily remove any object using that index :

var students = ["Ben", "Ivy", "Jordell", "Maxime"]
if let i = students.firstIndex(of: "Maxime") {
// students[i] = "Max"
students.remove(at: i)
}
print(students)
// Prints ["Ben", "Ivy", "Jordell"]

Here is the link: https://developer.apple.com/documentation/swift/array/2994720-firstindex

This is what I've used (Swift 5)...

    extension Array where Element:Equatable
{
@discardableResult
mutating func removeFirst(_ item:Any ) -> Any? {
for index in 0..<self.count {
if(item as? Element == self[index]) {
return self.remove(at: index)
}
}
return nil
}
@discardableResult
mutating func removeLast(_ item:Any ) -> Any? {
var index = self.count-1
while index >= 0 {
if(item as? Element == self[index]) {
return self.remove(at: index)
}
index -= 1
}
return nil
}
}


var arrContacts:[String] = ["A","B","D","C","B","D"]
var contacts: [Any] = ["B","D"]
print(arrContacts)
var index = 1
arrContacts.removeFirst(contacts[index])
print(arrContacts)
index = 0
arrContacts.removeLast(contacts[index])
print(arrContacts)

Results:

   ["A", "B", "D", "C", "B", "D"]
["A", "B", "C", "B", "D"]
["A", "B", "C", "D"]

Important: The array from which you remove items must contain Equatable elements (such as objects, strings, number, etc.)