Comparing Nsindexpath Swift

Comparing NSIndexPath Swift

Let's do a very simple test:

import UIKit

var indexPath1 = NSIndexPath(forRow: 1, inSection: 0)
var indexPath2 = NSIndexPath(forRow: 1, inSection: 0)
var indexPath3 = NSIndexPath(forRow: 2, inSection: 0)
var indexPath4 = indexPath1

println(indexPath1 == indexPath2) // prints "true"
println(indexPath1 == indexPath3) // prints "false"
println(indexPath1 == indexPath4) // prints "true"

println(indexPath1 === indexPath2) // prints "true"
println(indexPath1 === indexPath3) // prints "false"
println(indexPath1 === indexPath4) // prints "true"

Yes, it is safe to use == with NSIndexPath

As a side note, == in Swift is always for value comparisons. === is used for detecting when two variables reference the exact same instance. Interestingly, the indexPath1 === indexPath2 shows that NSIndexPath is built to share the same instance whenever the values match, so even if you were comparing instances, it would still be valid.

How to compare two NSIndexPaths?

Almost all Objective-C objects can be compared using the isEqual: method. So, to test equality, you just need [itemCategoryIndexPath isEqual:indexPath], and you're good to go. Now, this works because NSObject implements isEqual:, so all objects automatically have that method, but if a certain class doesn't override it, isEqual: will just compare object pointers.

In the case of NSIndexPath, since the isEqual: method has been overridden, you can compare the objects as you were to expect. But if I were to write a new class, MyObject and not override the method, [instanceOfMyObject isEqual:anotherInstanceOfMyObject] would effectively be the same as instanceOfMyObject == anotherInstanceOfMyObject.


You can read more in the NSObject Protocol Reference.

Comparing NSIndexPath

Since you're setting indexPathSelected to nil, you want to make sure it's non-nil before doing a compare.

if (self.indexPathSelected && [self.indexPathSelected compare:indexPath] == NSOrderedSame)
{
NSLog(@" %d %d %d %d", self.indexPathSelected.row, self.indexPathSelected.section, indexPath.row, indexPath.section);
}

According to the documentation on NSIndexPath's compare method:

Parameters

indexPath

Index path to compare.

This value must not be nil. If the value is nil, the behavior is
undefined.

indexPath comparison in TableView

[selectedRowsInSectionDictionary objectForKey:@(indexPath.section)] is an NSMutableArray reference, not an indexPath, so the comparison will never be true.

I would suggest that you store NSMutableIndexSet in your dictionary, rather than an array. Your code would then be something like:

NSMutableIndexSet *selectedSet = selectedRowsInSectionDictionary[@(indexPath.section)];
if ([selectedSet containsIndex:indexPath.row] {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
} else {
cell.accessoryType = UITableViewCellAccessoryNone;
}

To add/remove items to the dictionary using a 'toggle' you would use:

NSMutableIndexSet *selectedSet = selectedRowsInSectionDictionary[@(indexPath.section)];

if (selectedSet == nil) {
selectedSet = [NSMutableIndexSet new];
selectedRowsInSectionDictionary[@(indexPath.section)] = selectedSet;
}

if ([selectedSet containsIndex:indexPath.row]) {
[selectedSet remove:indexPath.row];
} else {
[selectedSet add:indexPath.row];
}

NSIndexPath can never be nil, comparison isn't allowed

You should not force unwrap and then check for nil - that would crash your app. What you should do is: drop the unwrap and then compare!

func handleLongPress(gestureRecognizer: UILongPressGestureRecognizer) {
let point = gestureRecognizer.locationInView(self.tableView)
let indexPath = self.tableView.indexPathForRowAtPoint(point)
if let touchedPath = indexPath {
if gestureRecognizer.state == .Began {
print(touchedPath.row)
}
}
}

How to compare elements in an array with indexPath.item?

make your model like this

struct ModelName{
var name: String
var rectangle: Bool
}

then you array which is selected items will be like this

var selectedItems = [ModelName]()

then in viewdidload or anywhere you are trying to initialise data you can do this

selectedItems.apped(ModelName(name: "name", rectangle: false)
selectedItems.apped(ModelName(name: "new", rectangle: true)
selectedItems.apped(ModelName(name: "newname", rectangle: false)
selectedItems.apped(ModelName(name: "namename", rectangle: false)

etc

then for cellforrow at do this

let item = selectedItems[indexPath.item]
cell.textlabel.text = item.name
if item.rectangle == true{
cell.rectButton.setImage(UIImage(named: "rectangle", for: .normal)
}else{
cell.rectButton.setImage(nil, for: .normal)}
return cell

I have tried with just name and rectangle you can do whatever you want if you don't want to initialse with any value make that variable nil

How to compare the data from current cell with its previous cell inside TableView Swift 4?

I think that to solve your issue, you should think about how you will store your JSON data.

You could begin by creating a struct called 'Product' which will store the product information and then by making it Equatable you can add a function which will allow you to compare the productID's:

/// Structure Of A Product
struct Product: Equatable{

var productID: Int
var productInfo: Int

static func == (lhs: Product, rhs: Product) -> Bool {
return lhs.productID == rhs.productID
}
}

Now to use this your structure you can create an Array variable to store your Products:

//Array To Store Array Of Product
var products = [Product]()

In this example I am just manually inputting the product information but you should handle this in a better way. However, it does illustrate one way you could 'start' to handle this:

   override func viewDidLoad() {
super.viewDidLoad()

//1. Create Products
let productOne = Product(productID: 471, productInfo: 123456)
let productTwo = Product(productID: 471, productInfo: 356697456)
let productThree = Product(productID: 472, productInfo: 1432)
let productFour = Product(productID: 473, productInfo: 4321)

//2. Add Them To The Products Array
addUnique(productOne)
addUnique(productTwo)
addUnique(productThree)
addUnique(productFour)

}

/// Checks That A Product Doesn't Exist
///
/// - Parameter product: Product
func addUnique(_ product: Product) {
if !products.contains(product) {
products.append(product)
}
}

In Step 1 we are manually creating the products.

In Step 2 we are calling the addUnique(_ product) function which will only allow unique Products to be stored.

After ensuring that there are no duplicate ProductID's, it should be easy for you to set the format as you like:

  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyCell
cell.productLabel.text = products[indexPath.row].productID
cell.productnameLabel.text = products[indexPath.row].productInfo
}

Of course you will need to fix any colouring of labels etc.

Using an Int type versus IndexPath type in Swift

Because the subscript expects an Int and you're passing an IndexPath which is not of type Int.

If you have a look at the Apple IndexPath Documentation, IndexPath has properties like row or section that are of type Int. You can use them to access an element from your array.

func item(at indexIWant: IndexPath) -> ToDoItem {
return toDoItems[indexIWant.row]
}

If you really want to access an array with IndexPath, you could extend the Array class. Now your code compiles but I am not sure if I recommend this code.

extension Array {
subscript(indexPath: IndexPath) -> Element {
get {
return self[indexPath.row]
}
set {
self[indexPath.row] = newValue
}
}
}

Why doesn't an NSIndexPath second value equal the indexPath.row?

In Swift, you should probably use IndexPath, which will bridge over to Objective-C API to the NSIndexPath class. (Apple Documentation)

The Swift overlay to the Foundation framework provides the IndexPath structure, which bridges to the NSIndexPath class. The IndexPath value type offers the same functionality as the NSIndexPath reference type, and the two can be used interchangeably in Swift code that interacts with Objective-C APIs. This behavior is similar to how Swift bridges standard string, numeric, and collection types to their corresponding Foundation classes.

While not an answer, using IndexPath instead of NSIndexPath does not exhibit the misleading behavior.

let indexPath = IndexPath(row: 11, section: 0)

po indexPath.row yields 11, as does the Variables View (see the _indexes structure below):

Variables view



Related Topics



Leave a reply



Submit