Swift 3: Remove specific string from array without knowing the indexPath? - arrays

I have a UICollectionView that has a bunch of cells. When I select these cells, they change color to look as if they have clearly been selected and I append that hashtag.hashtag_name (String) to my hashtagsArray. If I tap a category (fashion, food, hobbies or music), I append another array to that index path to give the user the cells for that specific category as you can see in my image example below.
What I would like is if I tap a already SELECTED cell to UNSELECT it, for that hashtag.hashtag_name to be removed from my hashtagArray. The issue is that the indexPath for the array that I add in is completely different to the array indexPath when I append it into the hashtagArray so I cannot remove it by calling self.hashtagArray.remove(Int). Here's my code...
import UIKit
class Hashtag: NSObject {
var hashtag_name: String?
var hashtag_color: String?
}
import UIKit
private let reuseIdentifier = "Cell"
class HashtagView: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var hashtagArray: [String] = []
var categoriesArray = [Hashtag]()
var fashionArray = [Hashtag]()
var isFashionSelected: Bool = false
var fashionArrayCount: [Int] = []
override func viewDidLoad() {
super.viewDidLoad()
self.navigationController?.navigationBar.tintColor = .white
navigationItem.title = "Hashtag"
self.collectionView?.backgroundColor = .white
self.collectionView?.register(HashtagCell.self, forCellWithReuseIdentifier: reuseIdentifier)
self.collectionView?.contentInset = UIEdgeInsetsMake(10, 0, 0, 0)
handleFetchCategories()
handleFetchFashionHashtags()
}
func insertCategoryAtIndexPath(element: [Hashtag], index: Int) {
categoriesArray.insert(contentsOf: element, at: index)
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = self.collectionView?.cellForItem(at: indexPath) as! HashtagCell
let hashtag = categoriesArray[indexPath.item]
if hashtag.hashtag_name == "FASHION" && isFashionSelected == false {
self.isFashionSelected = true
self.insertCategoryAtIndexPath(element: self.fashionArray, index: indexPath.item + 1)
self.collectionView?.reloadData()
} else if hashtag.hashtag_name == "FASHION" && isFashionSelected == true {
self.isFashionSelected = false
self.categoriesArray.remove(at: self.fashionArrayCount)
self.collectionView?.reloadData()
}
if hashtag.hashtag_name != "FASHION" && hashtag.hashtag_name != "FOOD" && hashtag.hashtag_name != "HOBBIES" && hashtag.hashtag_name != "MUSIC" {
if cell.isCellSelected == false {
cell.isCellSelected = true
if self.hashtagArray.contains(hashtag.hashtag_name!) {
cell.backgroundColor = .white
cell.hashtagLabel.textColor = greenColor
cell.layer.borderColor = greenColor.cgColor
} else {
self.hashtagArray.append(hashtag.hashtag_name!)
}
cell.backgroundColor = .white
cell.hashtagLabel.textColor = greenColor
cell.layer.borderColor = greenColor.cgColor
} else if cell.isCellSelected == true {
cell.isCellSelected = false
// REMOVE UNSELECTED CELL FROM ARRAY.
cell.backgroundColor = greenColor
cell.hashtagLabel.textColor = .white
cell.layer.borderColor = greenColor.cgColor
}
}
}

You can use the index(of: ) method on the array to get the index
if let index = hashtagArray.index(of: "SOMESTRING") {
hashtagArray.remove(at: index)
}

myArray = ["One","Two","Three","Four"]
myArray = myArray.filter{$0 != "Three"}
This will remove the "Three" from myArray. Also look at the following link too:
https://stackoverflow.com/a/44358108/8048468

You could use Array's index(of:) function to get the index of a known element and then remove it using remove(at:).
You could use filter(_:​) to create a new array excluding elements which match some check.
You could look at similar questions and write your own extension method to remove an object by value as in Array extension to remove object by value

Related

Compare 2 Results<CustomObject> by object of selected index of filteredList swift4

I have 2 lists of same custom object i.e. News
class News: Object {
#objc dynamic var title: String?
#objc dynamic var date: Date?
#objc dynamic var contentUrl: String?
}
and 2 lists are
var filteredList: Results<News>! = nil
var newsList: Results<News> {
get {
return realm.objects(News.self).sorted(byKeyPath: "date", ascending:
false)
}
}
I am filtering the list and the filtered data is storing in filteredList.
Now I want to send the IndexPath of newsList to the next VC. When I search in the list, filteredList is appending to the tableView which is absolutely correct. When I selecting row from filteredList it is giving index of filteredList. Now though user selects filteredList's index , it should compare with the object of newList and should return that indexPath /index of newsList
I have done it by my own way
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath:
IndexPath) {
searchController.dismiss(animated: true, completion: nil)
var sendIndex : IndexPath?
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
if !searchBarIsEmpty(){
for (index,news) in newsList.enumerated(){
if news.title == filteredList[indexPath.row].title{
sendIndex = IndexPath(row: index, section: 0)
}
}
}else{
sendIndex = indexPath
}
if let index = sendIndex{
let vc = NewsDetailsVC(collectionViewLayout: layout)
vc.tappedIndex = index
vc.title = "News Details"
vc.isSelectNews = true
self.navigationController?.pushViewController(vc, animated: true)
}
}
but it can be more optimise.. Please suggest some logic of optimisation
Here's a one-liner for finding the index to be sent.
if !searchBarIsEmpty() {
sendIndex = IndexPath(row: newsList.firstIndex(where: { $0.title == filteredList[indexPath.row].title }), section: 0)
}
Note: title is assumed to be the primary key. Compare with the appropriate primary key.

How to update a dictionary value in an array of dictionaries

I hate to ask this, as I feel I'm missing something super simple, but I've been banging my head on this issue, way too long.
When a user taps on a cell in my collectionView I store the indexPath.row and a value called timeOnIce in an array called tappedArray
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let cell = collectionView.cellForItem(at: indexPath) as! BenchCollectionViewCell
if cell.cellBackgroundImageView.image == UIImage(named: "collectionviewcell_60x60_white") {
cell.cellBackgroundImageView.image = UIImage(named: "collectionviewcell_60x60_blue")
let currentPlayerSelected = ["indexPath": indexPath.row, "timeOnIce": 0]
tappedArray.append(currentPlayerSelected)
} else {
cell.cellBackgroundImageView.image = UIImage(named: "collectionviewcell_60x60_white")
tappedArray = tappedArray.filter { $0["indexPath"] != indexPath.row }
}
}
A button to start a timer is pressed
func startTimer() {
//start the timer
timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateCounters), userInfo: nil, repeats: true)
} //startTimer
If two players are tapped (added to tappedArray) the array looks like the following:
tappedArray [["timeOnIce": 0, "indexPath": 1], ["timeOnIce": 0, "indexPath": 0]]
I'm having the hardest time trying to figure out how to update the timeOnIce in the dictionary to include the timerCounter
#objc func updateCounters() {
timerCounter += 1
for row in tappedArray {
print("row \(row)")
}
//Update tableview
tableView.reloadData()
} //updateCounters
This is what row prints out
row ["timeOnIce": 0, "indexPath": 2]
row ["timeOnIce": 0, "indexPath": 1]
row ["timeOnIce": 0, "indexPath": 0]
If I try the following in the for..in loop
row["timeOnIce"] = timerCounter
I get the following error
`Cannot assign through subscript: 'row' is a 'let' constant`
unless I change loop to the following:
for var row in tappedArray {
print("row \(row)")
row["timeOnIce"] = timerCounter
}
But the value doesn't get updated in the array...
Because Dictionary is a value type in Swift, the for loop makes a copy of the items in the array. To update the original, you can use an index into the array like this:
for row in tappedArray.indices {
print("row \(tappedArray[row])")
tappedArray[row]["timeOnIce"] = timerCounter
}
var dict1 = [String: Any]()
dict1.updateValue("Vanilla", forKey: "Ice Cream")
var dict2 = [String: Any]()
dict2.updateValue("World", forKey: "Hello")
var arr = [[String:Any]]()
arr.append(dict1)
arr.append(dict2)
print("arr-original: ", arr)
for (index, _) in arr.enumerated() {
if arr[index].contains(where: { $0.key == "Hello" }) {
arr[index]["Hello"] = "Dude"
}
}
print("arr-updated: ", arr)

Swift: Can't insert NSObject into Array as it wants a [String] instead

I have a model object called Hashtag. This simply contains a optional String variable called hashtagName. I fetch the data from my Firebase Database and append the hashtags to my fashionHashtags, which is a [Hashtag]. The issue I have is that I want to append that to my other categoriesArray by using the insertElementAtIndexPath function. I cannot do this as it wants an array of Strings and not an array of Hashtag. When I autocorrect it, it replaces it with fashionHashtags as! [String] but that creates another error. How do I fix this so it allows me to do so? I would like to stick to the Model Object way of doing things. Thank you guys. An answer would be highly appreciated. Code is below:
class Hashtag: NSObject {
vvar hashtagName: String?
}
private let reuseIdentifier = "Cell"
class HashtagView: UICollectionViewController, UICollectionViewDelegateFlowLayout {
var catagoriesArray: [String] = ["FASHION", "FOOD", "HOBBIES", "MUSIC"]
var fashionHashtags = [Hashtag]()
var foodHashtags = [Hashtag]()
var hobbiesHashtags = [Hashtag]()
var musicHashtags = [Hashtag]()
var hashtagsArray: [String] = []
override func viewDidLoad() {
super.viewDidLoad()
self.hashtagsArray.removeAll()
self.navigationController?.navigationBar.tintColor = .white
navigationItem.title = "Hashtag"
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Finished", style: .plain, target: self, action: #selector(finishSelectingHashtags))
self.collectionView?.backgroundColor = .white
self.collectionView?.register(HashtagCell.self, forCellWithReuseIdentifier: reuseIdentifier)
self.collectionView?.contentInset = UIEdgeInsetsMake(10, 0, 0, 0)
handleFetchFashionHashtags()
}
func insertElementAtIndexPath(element: [String], index: Int) {
catagoriesArray.insert(contentsOf: element, at: index)
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if indexPath.item == 0 {
insertElementAtIndexPath(element: fashionHashtags, index: indexPath.item + 1)
self.collectionView?.performBatchUpdates(
{
self.collectionView?.reloadSections(NSIndexSet(index: 0) as IndexSet)
}, completion: { (finished:Bool) -> Void in
})
}
}
Based upon my understanding, there could be a couple of different approaches. Here would be the approach of looping through the array of Hashtag objects and appending the hashtagName string property to the categoriesArray of strings.
for hashTagItem in fashionHashtags {
if let hashTag = hashTagItem.hashtagName {
// Appends to categoriesArray as a string
categoriesArray.append(hashTag)
}
}
Another approach would be to build a set of strings and then insert it as it makes sense.
var hashTagString: [Strings] = []
for hashTagItem in fashionHashtags {
if let hashTag = hashTagItem.hashtagName {
hashTagStrings.append(hashTag)
}
}
// Insert or add the hash tag strings as it makes sense
categoriesArray += hashTagStrings // Add all at once if it makes sense

How to delete specific NSObject in Array with Swift3

I made table view with friends contact info.
And Each cell has button if touched,
I want to insert the info to selected friend array
(by the array, I made another small view to slide up with the friends list).
But If user the button one more,
I want to delete the friend Info in the selected friend array.
I know how to append to array,
but I don't know how to erase the specific item(NSObject) in array
by not using index.
my source code is below
class FriendModel : NSObject {
dynamic var index : ""
dynamic var thumbnail : ""
dynamic var name : ""
}
and In view controller class,
var selectedList = [FriendModel]()
#IBAction func SelectAct(_ sender: Any) {
let chooseBtn = sender as! UIButton
let indexPath = NSIndexPath(row: chooseBtn.tag, section:0)
let cell = tableView.cellForRow(at: indexPath as IndexPath) as! FriendsListSendCell
// when selected button is pushed
if chooseBtn.isSelected == true {
chooseBtn.isSelected = false
count = count! - 1
if self.count! < 1 {
self.windowShowUp = false
UIView.animate(withDuration: 0.1, delay: 0.1, options: [], animations:{self.selectedBoard.center.y += 80 }, completion: nil)
self.checkNumLabel.text = ""
}else{
}
//////////////////////////here////////////////////////////
//////////////////how to erase the FriendModel(NSObject) in selectedList.
}
//when the unselected button is pushed
else {
//instance for append the friend info
let friendInfo = FriendModel()
chooseBtn.isSelected = true
count = count! + 1
friendInfo.thumbnail = cell.thumbnail
friendInfo.name = cell.nameLabel.text!
//add friend info to selectedList
self.selectedList.append(friendInfo)
print("\(self.selectedList)")
if self.windowShowUp! == false{
self.windowShowUp = true
UIView.animate(withDuration: 0.1, delay: 0.1, options: [], animations:{self.selectedBoard.center.y -= 80 }, completion: nil)
}else{
}
}
}
You can use index(where:) to get index of your object and then remove item at index position.
class FriendModel {
var index = ""
var thumbnail = ""
var name = ""
}
let fm0 = FriendModel()
fm0.index = "100"
fm0.thumbnail = "tell.png"
fm0.name = "Phillips"
let fm1 = FriendModel()
fm1.index = "200"
fm1.thumbnail = "ask.png"
fm1.name = "Allen"
var array = [FriendModel]()
array.append(fm0)
array.append(fm1)
// The index below is an index of the array. Do not confuse with the FriendModel.index
let index = array.index {
return $0.thumbnail == "ask.png" && $0.name == "Allen"
}
array.forEach { print($0.name) }
print("Array index:", index ?? "n/a")
array.remove(at: index!)
array.forEach { print($0.name) }
You could use MirekE's solution which would work but here's an alternative solution.
First step would be identifying what the unique identifier on your FriendModel object is such as an id property.
Then on your model, since it is an NSObject, override the isEqual function like this:
override public func isEqual(object: AnyObject?) -> Bool {
let friend = object as? FriendModel
if self.id == friend?.id { return true }
return false
}
At this point you can use your desired form of iteration to find your element in the array and use remove.

Setting a cells textLabel from an array of [String]()

Trying to access and set my cells textLabel and detail text label to objects i have appended to the array. Im not to sure how to use the right syntax in this case. thanks for the help!
heres the objects I've appended from parse in my for loop.
var customers = [String]()
for object in objects {
self.customers.append(object["customerName"] as! String)
self.customers.append(object["customerStreetAddress"] as! String)
cellForRowAtIndexPath {
cell.textLabel.text = //I want the objects["customerName"] here
cell.detailTextLabel.text = // objects["customerStreetAddress"] here
}
You could try this.
var customers = [String]()
var number = -1
for object in objects {
self.customers.append(object["customerName"] as! String)
self.customers.append(object["customerStreetAddress"] as! String)
cellForRowAtIndexPath {
++number
if number + 1 <= customers.count {
cell.textLabel.text = customers[number]//I want the objects["customerName"] here
}
++number
if number + 1 <= customers.count {
cell.detailTextLabel.text = customers[number]// objects["customerStreetAddress"] here
}
}
}

Resources