UiCollectionView 单元格选择错误

Posted

技术标签:

【中文标题】UiCollectionView 单元格选择错误【英文标题】:UiCollectionView Cell Selection Error 【发布时间】:2016-03-07 14:16:41 【问题描述】:

我已经使用 Alamofire 和 SwiftyJSON 来填充 UiCollectionview 并且它工作正常,但是 didSelectItemAtIndexPath 函数显示数组超出索引我认为我已经打印了数组计数并且它不是空的

任何建议

这是我的代码:-

型号

import Foundation

class ProductModel 
private var _ProductItemId: String!
private var _ProductMainCategory: String!
private var _ProductCategoryId: String!
private var _ProductName: String!
private var _ProductItemNo: String!
private var _ProductAvalaibility: String!
private var _ProductSeoDesc: String!
private var _ProductImageURL: String!
private var _ProductBrand_ID: String!
private var _ProductCat_name: String!

//Level 1
private var _ProductTotalQuantity : String!
private var _Productprice : String!
private var _ProductSalePrice : String!
private var _ProductWeightName : String!
private var _ProductCode : String!




var ProductItemId : String 
    return _ProductItemId


var ProductMainCategory : String 
    return _ProductMainCategory


var ProductCategoryId : String 
    return _ProductCategoryId


var ProductName : String 
    return _ProductName


var ProductItemNo : String 
    return _ProductItemNo


var ProductAvalaibility : String 
    return _ProductAvalaibility


var ProductSeoDesc : String 
    return _ProductSeoDesc


var ProductImageURL : String 
    return _ProductImageURL


var ProductBrand_ID: String 
    return _ProductBrand_ID


var ProductCat_name: String 
    return _ProductCat_name


//Level 1
var ProductTotalQuantity : String 
    return _ProductTotalQuantity


var Productprice : String 
    return _Productprice


var ProductSalePrice : String 
    return _ProductSalePrice


var ProductWeightName : String 
    return _ProductWeightName


var ProductCode : String 
    return _ProductCode




//Initilizer
init(ProductImageURL : String, ProductName : String, Productprice : String, ProductSalePrice : String)


    self._ProductName = ProductName
    self._ProductImageURL = ProductImageURL//

    //Level 1
    self._Productprice = Productprice//
    self._ProductSalePrice = ProductSalePrice//


我的 CollectionView 委托和数据源

 func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell 
    if let cell = collectionView.dequeueReusableCellWithReuseIdentifier("ProductCell", forIndexPath: indexPath)as? ProductCell 

        let _prod: ProductModel!
            _prod = prod [indexPath.row]
        cell.configureCell(_prod)
        return cell
    
    else
        return UICollectionViewCell()
    




func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) 
    let prodDetail: ProductModel!
    prodDetail = prod[indexPath.row] //error Array index out of range 
    print(prodDetail.Productprice)
    performSegueWithIdentifier("productDetailSegue", sender: prodDetail)



func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int 
    //if inSearchMode
        //return filteredProd.count
  //  
    return prod.count


func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int 
    return 1

调用API和解析

    Alamofire.request(.POST, "http://www.picknget.com/webservice/index.php/Home/filter_grocery_product_practice/", parameters: parameterDictionary as? [String : AnyObject])
        .responseJSON  response in
            if let value = response.result.value 
                let json = JSON(value)
                print(json)
                if let _statusCode = json["status"].string 
                    // print("the ststus code is ", _statusCode)
                    if (_statusCode == "1")
                        self.parseJSON(json)
                    
                    if (_statusCode == "0")
                        SwiftSpinner.hide(
                            self.callAlert("OOP's", _msg: "No More Product is available in this section right now")
                        )
                    
                
                //print ("json result ", json)

            
        .responseString  response in
            //print("response ",response.result.value)
    


func parseJSON(json: JSON) 
    for result in json["cat"].arrayValue 
        let name = result["Name"]

        let aString: String = "\(result["ImageURL"])"
        let product_Image_Url  = aString.stringByReplacingOccurrencesOfString("~", withString: "http://www.picknget.com", options: NSStringCompareOptions.LiteralSearch, range: nil)
        let price = result["cat_price"][0]["Price"].string
        let SalePrice = result["cat_price"][0]["SalePrice"].string


        let product = ProductModel(ProductImageURL: "\(product_Image_Url)", ProductName: "\(name)", Productprice: "\(price!)", ProductSalePrice: "\(SalePrice!)")
        prod.append(product)
    

    print("@@@@@@@@")
    print(prod.count)
    dispatch_async(dispatch_get_main_queue(),
        self.productCollect.reloadData()
    );

【问题讨论】:

确保prod(可能是self.prod)只能从主线程访问,并且不会被两个或多个线程同时修改。使用 tmp 变量从网络中获取产品。然后,在主线程上分配self.prod获得的产品。每当self.prod 更改时,随后也调用reloadData 以获取集合视图。 (提示:使用更好的名称,例如 products 而不是 prod @couchDeveloper 感谢您的回复先生,一切正常,但我无法弄清楚为什么只有在选择单元格时数组索引超出范围,如果数组为空则它不应该在集合视图中显示任何单元格对吗?任何建议先生 如果您同时从两个线程更改prod,则数组索引将变得不同步。您的代码没有显示 如何 您设置 prod - 所以,这只是一个怀疑。您可以检查您的代码,例如,如果网络请求中的完成处理程序更改 prod 并且如果它在辅助线程上运行(很可能),那么这就是问题所在。 @couchDeveloper 先生,我已经更新了 API 调用和解析部分代码先生,请看一下 :) @couchDeveloper 先生,现在开始工作了,先生.. 【参考方案1】:

根据您的 cmets,我认为问题与您如何为 Collection View 设置获取的产品有关。

函数parseJSON 很可能在辅助线程上执行。这实际上是方法responseJSON的完成处理程序的相同执行上下文。

在函数parseJSON 中有这样的语句:

    prod.append(product)

这里,prod 应该是全局变量或视图控制器的成员变量!使其成为函数parseJSON中的局部变量!

您的视图控制器也应该具有该数组的属性,例如products。这充当视图控制器的“模型”。只能从主线程访问。

parseJSON 中为视图控制器分配产品如下:

func parseJSON(json: JSON) 
    var tmpProducts: [Product] = []
    for result in json["cat"].arrayValue 
        let name = result["Name"]

        let aString: String = "\(result["ImageURL"])"
        let product_Image_Url  = aString.stringByReplacingOccurrencesOfString("~", withString: "http://www.picknget.com", options: NSStringCompareOptions.LiteralSearch, range: nil)
        let price = result["cat_price"][0]["Price"].string
        let SalePrice = result["cat_price"][0]["SalePrice"].string


        let product = ProductModel(ProductImageURL: "\(product_Image_Url)", ProductName: "\(name)", Productprice: "\(price!)", ProductSalePrice: "\(SalePrice!)")
        tmpProducts.append(product)
    

    dispatch_async(dispatch_get_main_queue(),
        self.products = tmpProducts   // assuming `self` is the ViewController
        self.productCollect.reloadData()
    );

注意:您需要相应地更改您的数据源委托,例如访问“模型”(self.products.count)等

【讨论】:

先生,上面的代码运行良好,但是当我通过滚动视图添加更多数据时,现有数据将被新数据替换 @AbdulKarim self.products.appendContentsOf(tmpProducts) 怎么样?而不是self.products = tmpProducts ? 先生,您的想法在产品的过滤和分类方面效果很好,但仍然存在一个问题,先生。虽然我使用 self.products.appendContentsOf(tmpProducts) 它的作用是 - 它附加了以前的产品加载了第一个 API 调用任何建议先生

以上是关于UiCollectionView 单元格选择错误的主要内容,如果未能解决你的问题,请参考以下文章

无论在 UICollectionView 中选择啥 IndexPath,只有最后一个单元格会被突出显示

UIcollectionview 一次选择多个单元格

重新加载数据后根据要求更新后未显示 uicollectionview 单元格

UICollectionView 点击选择多个单元格

UICollectionView 单元格选择问题 - 加载视图时只能选择可见区域上的单元格

UICollectionView,单元格选择不起作用,单元格滚动正常