Selectively Remove and Delete Objects from a Nsmutablearray in Swift

Remove duplicates from a NSMutableArray with objects added in a 'for' loop

I believe you want to be using an NSOrderedSet. Here's the documentation on it:

http://developer.apple.com/library/mac/#documentation/Foundation/Reference/NSOrderedSet_Class/Reference/Reference.html

NSMutableArray remove element at row and rearrange all the rows after that

This happens automatically when you call removeObjectAtIndex. From the class reference documentation:

To fill the gap, all elements beyond
index are moved by subtracting 1 from
their index.

Details of using fast enumeration on a copy of an NSMutableArray to remove objects

Copying an array does a "shallow copy". It creates a new array object, then stores pointers to the objects in the first array. It does not create new objects.

Think of an array like an address book. It lists the addresses of your friends' houses. If I make a copy of your address book, then I have a copy of the list of the addresses. The address books do not contain houses.

If I erase an entry from my copy of the address book, it does not erase the same entry from your address book. Nor does it destroy any houses.

In your loop 2 code, you are looping through the copy, then telling your original array to delete certain objects. They are deleted from the original array, but not from the copy. (Which is good, because as you say, mutating an array as you iterate through it causes a crash.)

Note that arrays can contain more than one pointer to the same object, just like addresses can contain the same address more than once. (If a friend changes her name when she gets married, you might write her into your address under he married name and leave the entry under her maiden name as well. Both addresses point to the same house.)

Note that the removeObject method that you are using removes ALL entries for an object. It's like you're saying "erase every entry in my address book for 123 Elm street". If you only want to remove one entry of a duplicate set then you need to use removeObjectAtIndex instead, and you would need to change your code to make that work.

Swift code problem - trying to cast objects out from a NSMutableArray as a custom object

Better approach would be to use JSONDecoder() instead of a JSONSerailizer. Try using the following code.

struct User: Codable {
var userId, firstName, lastName, userSessionId: String

enum CodingKeys: String, CodingKey {
case userId = "Userid"
case firstName = "First_Name"
case lastName = "Last_Name"
case userSessionId = "Session_ID"
}
}

func parseJSON(_ data: Data) {
do {
let users = try JSONDecoder().decode([User].self, from: data)
users.forEach { user in
print("users first name:", user.firstName)
}
} catch {
print(error.localizedDescription)
}
}

Remove Specific Array Element, Equal to String - Swift

You can use filter() to filter your array as follow

var strings = ["Hello","Playground","World"]

strings = strings.filter { $0 != "Hello" }

print(strings) // "["Playground", "World"]\n"

edit/update:

Xcode 10 • Swift 4.2 or later

You can use the new RangeReplaceableCollection mutating method called removeAll(where:)

var strings = ["Hello","Playground","World"]

strings.removeAll { $0 == "Hello" }

print(strings) // "["Playground", "World"]\n"

If you need to remove only the first occurrence of an element we ca implement a custom remove method on RangeReplaceableCollection constraining the elements to Equatable:

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

Or using a predicate for non Equatable elements:

extension RangeReplaceableCollection {
@discardableResult
mutating func removeFirst(where predicate: @escaping (Element) throws -> Bool) rethrows -> Element? {
guard let index = try firstIndex(where: predicate) else { return nil }
return remove(at: index)
}
}

var strings = ["Hello","Playground","World"]
strings.removeFirst("Hello")
print(strings) // "["Playground", "World"]\n"
strings.removeFirst { $0 == "Playground" }
print(strings) // "["World"]\n"

Remove objects with duplicate properties from Swift array

I am going to suggest 2 solutions.

Both approaches will need Post to be Hashable and Equatable

Conforming Post to Hashable and Equatable

Here I am assuming your Post struct (or class) has an id property of type String.

struct Post: Hashable, Equatable {
let id: String
var hashValue: Int { get { return id.hashValue } }
}

func ==(left:Post, right:Post) -> Bool {
return left.id == right.id
}

Solution 1 (losing the original order)

To remove duplicated you can use a Set

let uniquePosts = Array(Set(posts))

Solution 2 (preserving the order)

var alreadyThere = Set<Post>()
let uniquePosts = posts.flatMap { (post) -> Post? in
guard !alreadyThere.contains(post) else { return nil }
alreadyThere.insert(post)
return post
}

NSMutablearray move object from index to index

id object = [[[self.array objectAtIndex:index] retain] autorelease];
[self.array removeObjectAtIndex:index];
[self.array insertObject:object atIndex:newIndex];

That's all. Taking care of the retain count is important, since the array might be the only one referencing the object.

How do you clear attributes from NSMutableAttributedString?

You can remove all of the attributes like this:

NSMutableAttributedString *originalMutableAttributedString = //your string…

NSRange originalRange = NSMakeRange(0, originalMutableAttributedString.length);
[originalMutableAttributedString setAttributes:@{} range:originalRange];

Note that this uses setAttributes (not add). From the docs:

These new attributes replace any attributes previously associated with the characters in aRange.

If you need to do any of it conditionally, you could also enumerate the attributes and remove them one-by-one:

[originalMutableAttributedString enumerateAttributesInRange:originalRange
options:kNilOptions
usingBlock:^(NSDictionary *attrs, NSRange range, BOOL *stop) {
[attrs enumerateKeysAndObjectsUsingBlock:^(NSString *attribute, id obj, BOOL *stop) {
[originalMutableAttributedString removeAttribute:attribute range:range];
}];
}];

According to the docs this is allowed:

If this method is sent to an instance of NSMutableAttributedString, mutation (deletion, addition, or change) is allowed.


Swift 2

If string is a mutable attributed string:

string.setAttributes([:], range: NSRange(0..<string.length))

And if you want to enumerate for conditional removal:

string.enumerateAttributesInRange(NSRange(0..<string.length), options: []) { (attributes, range, _) -> Void in
for (attribute, object) in attributes {
string.removeAttribute(attribute, range: range)
}
}

How can I conform to the Strideable protocol in Swift?

Here's a definition of the protocol: Stridable

You can implement it like this:

final class Foo: Strideable {
var value: Int = 0
init(_ newValue: Int) { value = newValue }
func distanceTo(other: Foo) -> Int { return other.value - value }
func advancedBy(n: Int) -> Self { return self.dynamicType(value + n) }
}

func ==(x: Foo, y: Foo) -> Bool { return x.value == y.value }
func <(x: Foo, y: Foo) -> Bool { return x.value < y.value }

let a = Foo(10)
let b = Foo(20)

for c in stride(from: a, to: b, by: 1) {
println(c.value)
}

You need to provide the functions distanceTo, advancedBy and the operators == and <. There is more information about these functions in the documentation I linked.



Related Topics



Leave a reply



Submit