how to single select cell in collection view..?

This is happening because the collectionView reuse the cells;

you should store the selected cell's IndexPath in a variable:

ObjC :

@property (nonatomic, retain) NSIndexPath *selectedIndexPath;

-(void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath {

    UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];

    cell.layer.backgroundColor = [UIColor blackColor].CGColor;
    NSLog(@"INDEXPATH:-%ld",(long)indexPath.row);

    self.selectedIndexPath = indexPath
}
-(void)collectionView:(UICollectionView *)collectionView didDeselectItemAtIndexPath:(NSIndexPath *)indexPath{

    UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
    cell.layer.backgroundColor = [UIColor whiteColor].CGColor;

    self.selectedIndexPath = nil
}

Swift :

var selectedIndexPath: IndexPath?

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath)

    cell.layer.backgroundColor = UIColor.black

    self.selectedIndexPath = indexPath
}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    let cell = collectionView.cellForItem(at: indexPath)

    cell.layer.backgroundColor = UIColor.white

    self.selectedIndexPath = nil
}

than in "cell for row at indexPath" check :

ObjC :

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {

    UICollectionViewCell* cell = [collectionView cellForItemAtIndexPath:indexPath];
    cell.layer.cornerRadius = cellWidth / 2.0;
    if (self.selectedIndexPath != nil && indexPath == self.selectedIndexPath) {
        cell.layer.backgroundColor = [UIColor blackColor].CGColor;
    else {
        cell.layer.backgroundColor = [UIColor whiteColor].CGColor;
   }

    return cell
}

Swift :

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.cellForItem(at: indexPath)
    cell.layer.cornerRadius = cellWidth / 2

    if self.selectedIndexPath != nil && indexPath == self.selectedIndexPath {
        cell.layer.backgroundColor = UIColor.black
    else {
        cell.layer.backgroundColor = UIColor.white
    }
}

Thanks for Alberto Scampini this code for swift 3.1

var selectedIndexPath: IndexPath?

 func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = self.collectionView.dequeueReusableCell(withReuseIdentifier: "SegmentChoiceCVCell", for: indexPath) as! SegmentChoiceCVCell
    //configure cell

    if selectedIndexPath != nil && indexPath == selectedIndexPath {
        cell.checkIcon.backgroundColor = UIColor.black

    }else{

        cell.checkIcon.backgroundColor = UIColor.white
    }

    return cell

}



func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {

    let cell = collectionView.cellForItem(at: indexPath) as! SegmentChoiceCVCell

        cell.checkIcon.backgroundColor = UIColor.black
    self.selectedIndexPath = indexPath

}

func collectionView(_ collectionView: UICollectionView, didDeselectItemAt indexPath: IndexPath) {
    let cell: SegmentChoiceCVCell = collectionView.cellForItem(at: indexPath) as! SegmentChoiceCVCell

        cell.checkIcon.backgroundColor = white
    selectedIndexPath = nil
}

I know that I am late to the party. I had the same problem. And after looking around in stackoverflow. Here's my solution. It may help starters understand the UICollectionViewCell a bit easier.

"cellForItemAtIndexPath" method controls how the cell will be display. And cells that are off-screen will not be updated.

Swift 4

First, you need to sub-class your cell.

class SubclassedCell: UICollectionViewCell {

      @IBOutlet var cellImage: UIImageView!
      @IBOutlet var cellCaption: UILabel!

}

extension SubclassedCell{

   func highlightEffect(){
      self.layer.borderWidth = 3.0
      self.layer.borderColor = UIColor.lightGray.cgColor
   }

   func removeHighlight(){
      
      self.layer.borderColor = UIColor.clear.cgColor
   }

} 

And now for the "cellForItemAt" method.

   func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    
    
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "blahblahblah", for: indexPath) as! SubclassedCell
  
    
    cell.cellImage.image = yourImages[indexPath.item]
    cell.cellCaption.text = yourImageNames[indexPath.item]
    cell.removeHighlight()  // Call subclassed cell method.
    if indexPath.item == selectedItem {
        cell.highlightEffect() // Call subclassed cell method.
        preSelected = IndexPath(item: indexPath.item, section: indexPath.section)
        
        
    }
    
    collecttionRef = collectionView
    return cell
    
}

Then, for the "didSelectItemAt" method

  func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath){
    
    collectionView.allowsMultipleSelection = false
    if let cell = collectionView.cellForItem(at: indexPath) as! SubclassedCell?{
        let indexPathData = NSKeyedArchiver.archivedData(withRootObject: indexPath)
        UserDefaults.standard.set(indexPathData,forKey: "backgroundIndexPath")
        //I got some unwrapped crash for my App so I have to use UserDefault to fix the unwrapped problem. You could ignore these both lines.

        selectedItem = indexPath.item //selectedItem is used in the "cellForItemAt" method above.
        
        

        collectionView.reloadData() //update all cells. It could be heavy if you have many cells.
        
    }
   
}