楽天APIからCollectionViewに商品名、値段、画像を表示

#今回の内容

<img width="150" alt="69567B63-71CE-4194-A7B9-91DFE0D00814_1_201_a.jpeg" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1466343/bd67b59f-45c0-78f4-795e-329955957170.jpeg">

* 上の画像は、取得したデータを表示する前の`CollectionView`です。

#コード

##Model

```Swift:GetAPIDatas
struct GetAPIDatas {
    
    let itemName:String?
    let itemPrice:String?
    let mediumImageUrl:String?
}
```

```Swift:AlamofireModel
import Alamofire
import SwiftyJSON

class AlamofireModel{
    
    public var getAPIResultArray = [GetAPIDatas]()
    
}

extension AlamofireModel{
    
    public func getAPIDatas(searchKeyWord:String?){
        
        guard let keyWord = searchKeyWord else { return }
       
        let apiKey = "APIKey"

        AF.request(apiKey, method: .get, parameters: nil, encoding: JSONEncoding.default).responseJSON { [self](response) in
            
            switch response.result{
            
            case .success:
                getAPIResultArray = []
                
                let json = JSON(response.data as Any)
                    
                for getDataCount in 0...29{
                        
                    if (json["Items"][getDataCount]["Item"]["itemName"].string != "" && 
                        json["Items"][getDataCount]["Item"]["itemPrice"].string != "" && 
                        json["Items"][getDataCount]["Item"]["mediumImageUrls"][getDataCount]["imageUrl"].string != "") == true{

                            let getData = GetAPIDatas(itemName: json["Items"][getDataCount]["Item"]["itemName"].string,
                                                      itemPrice: String(json["Items"][getDataCount]["Item"]["itemPrice"].int!),
                                                      mediumImageUrl: json["Items"][getDataCount]["Item"]["mediumImageUrls"][0]["imageUrl"].string)
                            
                            getAPIResultArray.append(getData)
                        }
                    }
           
            case .failure(let error):
                print(error.errorDescription as Any)            
            }
        }
    }
}

extension String{
    
    var urlEncoded:String{
        
        let charset = CharacterSet.alphanumerics.union(.init(charactersIn: "/?-._~"))
        let remove = removingPercentEncoding ?? self
        
        return remove.addingPercentEncoding(withAllowedCharacters: charset) ?? remove
    }
}
```

##View

```Swift:CollectionCustomCell
import UIKit

class CollectionCustomCell: UICollectionViewCell {
       
    @IBOutlet weak var itemImageView: UIImageView!
    @IBOutlet weak var itemNameLabel: UILabel!
    @IBOutlet weak var itemPriceLabel: UILabel!
        
    override func awakeFromNib() {
        super.awakeFromNib()
        
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
               
    }
    
    override func prepareForReuse() {
        super.prepareForReuse()
        
        itemImageView.image = UIImage(named: "")
        itemNameLabel.text = ""
        itemPriceLabel.text = ""
    }
}
```

```Swift:Indicator
import UIKit

class Indicator{
    
    public let indicatorView = UIActivityIndicatorView()
    
    public func showIndicator(targetView:UIView){
        indicatorView.center = targetView.center
        indicatorView.style = .large
        indicatorView.color = .systemRed
        
        targetView.addSubview(indicatorView)
        
        indicatorView.startAnimating()
    }
}
```

##Controller

```Swift:ViewController
import UIKit
import SDWebImage

class ViewController: UIViewController {

    @IBOutlet weak var searchTextField: UITextField!
    @IBOutlet weak var searchButton: UIButton!
    @IBOutlet weak var collectionView: UICollectionView!
  
    private let collectionViewFlowLayout = UICollectionViewFlowLayout()
    
    private let alamofireModel = AlamofireModel()
    private let indicator = Indicator()
   
    override func viewDidLoad() {
        super.viewDidLoad()
       
        collectionView.register(UINib(nibName: "CollectionCustomCell", bundle: nil), forCellWithReuseIdentifier: "Cell")
        collectionView.dataSource = self
    }
    
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        
        collectionViewFlowLayout.sectionInset = UIEdgeInsets(top: 5, left: 5, bottom: 5, right: 5)
        collectionView.collectionViewLayout = collectionViewFlowLayout
    }

    @IBAction func search(_ sender: UIButton) {
        
        alamofireModel.getAPIDatas(searchKeyWord: searchTextField.text)
        indicator.showIndicator(targetView: view)
        DispatchQueue.main.asyncAfter(deadline: .now() + 3) { [self] in
            
            indicator.indicatorView.stopAnimating()
            collectionView.reloadData()
        }
    }
    
}

extension ViewController:UICollectionViewDataSource{
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    
        return alamofireModel.getAPIResultArray.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath) as! CollectionCustomCell
        
        cell.itemImageView.sd_setImage(with: URL(string: alamofireModel.getAPIResultArray[indexPath.row].mediumImageUrl!), completed: nil)
        cell.itemNameLabel.text = alamofireModel.getAPIResultArray[indexPath.row].itemName
        cell.itemPriceLabel.text = "\(alamofireModel.getAPIResultArray[indexPath.row].itemPrice ?? "読み込みERROR")円"
        
        return cell
    }
    
}

extension ViewController:UICollectionViewDelegateFlowLayout{
    
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        
        return CGSize(width: collectionView.frame.width / 2 - 10, height: collectionView.frame.width / 2 - 10)
    }
}
```
# 終わり
ご指摘、ご質問などありましたら、コメントまでお願い致します。