アプリ内課金ローカル認証(デバッグ用)

サーバー側で検証に使うレシートの内容をアプリ内で確認したい場合のコード

func receiptValidation() {
        let receiptUrl = Bundle.main.appStoreReceiptURL
        let receiptData = try! Data(contentsOf: receiptUrl!)

        let requestContents = [
            "receipt-data": receiptData.base64EncodedString(options: .endLineWithCarriageReturn),
            "password": "共有シークレット"
        ]

        let requestData = try! JSONSerialization.data(withJSONObject: requestContents, options: .init(rawValue: 0))

        var request = URLRequest(url: URL(string: "https://sandbox.itunes.apple.com/verifyReceipt")!)
        request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField:"content-type")
        request.timeoutInterval = 5.0
        request.httpMethod = "POST"
        request.httpBody = requestData

        let session = URLSession.shared
        let task = session.dataTask(with: request, completionHandler: {(data, response, error) -> Void in

            guard let jsonData = data else {
                return
            }
            do {
                let json:Dictionary<String, AnyObject> = try JSONSerialization.jsonObject(with: jsonData, options: .init(rawValue: 0)) as! Dictionary<String, AnyObject>

                guard let receipts:Dictionary<String, AnyObject> = json["receipt"] as? Dictionary<String, AnyObject> else {
                    return
                }
                print(receipts)

            } catch let error {
                print("SKPaymentManager : Failure to validate receipt: \(error)")
            }
        })
        task.resume()
    }

Carthageを使ってフレームワークを導入

導入するもの
1. Alamofire
2. ObjectMapper
3. RxSwift
 

プロジェクトの配下で以下のコマンドをうつ

$ touch Cartfile
$ vim Cartfile

Vimに導入したいライブラリを記載

github "Alamofire/Alamofire"  
github "Hearst-DD/ObjectMapper"  
github "ReactiveX/RxSwift"  

ビルドする

$ carthage update --platform iOS

プロジェクトを以下のように変更する
1.+ボタンから、Add Otherをタップ
プロジェクト > Carthage > Build > iOS >追加したいフレームワークを選択 f:id:ichi6161:20180325133238p:plain

Build Phase に以下を追加

$(SRCROOT)/Carthage/Build/iOS/Alamofire.framework
$(SRCROOT)/Carthage/Build/iOS/RxSwift.framework
$(SRCROOT)/Carthage/Build/iOS/ObjectMapper.framework

f:id:ichi6161:20180325133245p:plain

以上

Swift: CollectonViewの列と行を設定する

CollectoinViewの列と行を変更していきたいと思います。

開始の状態
参考: Swift: カスタムCollectionViewセル - ichi6161’s diary

f:id:ichi6161:20180225192610p:plain

手順

  1. 準備
  2. セルの大きさを設定
  3. マージンを設定

1. 準備

UICollectionViewDelegateFlowLayoutを採用する

class FirstViewController: UIViewController, UICollectionViewDelegateFlowLayout, 
         UICollectionViewDataSource {

viewDidLoadにcollectionViewのdelegateをselfにセット
(UICollectionViewDelegateFlowLayoutはUICollectionViewDelegateを継承している)

    collectionView.delegate = self



2. セルの大きさを設定

ここまでできたら、実際にCollectionViewの列と行を決めていく

例)2列にする場合

func collectionView(_ collectionView: UICollectionView,
                        layout collectionViewLayout: UICollectionViewLayout,
                        sizeForItemAt indexPath: IndexPath) -> CGSize {

  // 横幅を画面サイズの約半分にする
        let cellSize:CGFloat = self.view.bounds.width/2 - 4
        return CGSize(width: cellSize, height: cellSize)
}



結果
f:id:ichi6161:20180225194131p:plain

このように1列になってしまった。
セルの横幅が画面サイズの半分であれば、2列で表示されるはずなのに...。

Stroryboardの設定を確認
f:id:ichi6161:20180225194552p:plain


Min Spacingが10に設定してあるため、思うようにいかなかったらしい。 試しに Min Spacingを変更してみる
(For Cells :2 , For Lines :2)


結果
f:id:ichi6161:20180225194912p:plain

2列を表示することには成功!!
が、しかし、4行目のセルが半分見えている状態になっている。
この状態から、3行目までが表示されている状態に修正を加える。



3. Marginの設定

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        //外枠のマージン(top , left , bottom , right)
        return UIEdgeInsetsMake(20 , 2 , 20 , 2 )  
    }
    

// 水平方向におけるセル間のマージン
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
  // セルの左右に
        return 0
    }
    
// 垂直方向におけるセル間のマージン
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 20
    }



結果
f:id:ichi6161:20180225201638p:plain


できた。
(端末によっては、3行きっかり表示されない可能性があるので、 さらに細かい修正は必要になる。)

Swift: カスタムCollectionViewセル

  1. StorryboardにCollectionViewを設定
  2. CollectionviewのdataSourceを設定
  3. カスタムセル用のクラスを作成 (xibファイルもセットで)
  4. StorryboardにCollectionViewのセルをタップして、identiferとクラスを設定
  5. コードでCell用に作成したxibファイルをCollectionViewに登録
  6. datasource実装

1 StorryboardにCollectionViewを設定

f:id:ichi6161:20180225182408p:plain

2 CollectionviewのdataSourceを設定

import UIKit

class FirstViewController: UIViewController, UICollectionViewDataSource {


    @IBOutlet weak var collectionView: UICollectionView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        collectionView.detaSource = self
     }

// 以下省略



3 カスタムセル用のクラスファイルを作成する

f:id:ichi6161:20180225182943p:plain

セルにラベルを設定する場合はIBOutletをこのクラスに結びつける。 f:id:ichi6161:20180225184018p:plain

4 StorryboardにCollectionViewのセルをタップして、identiferとクラスを設定

f:id:ichi6161:20180225183107p:plain
f:id:ichi6161:20180225183114p:plain

5. コードでCell用に作成したxibファイルをCollectionViewに登録(xibファイル名とitdentiferが必要)

ViewDidLoadに以下のコードを追加する

self.collectionView.register(UINib (nibName: "CustomCell", bundle: nil), forCellWithReuseIdentifier: "CustomCell")



6. datasource実装

    public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int{
        return 10
    }

    
    public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell{
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomCell", for: indexPath) as! CustomCell
        return cell
    }



f:id:ichi6161:20180225184156p:plain
以上

複数のストーリーボード

複数のストーリーボードを使って、NavigationControllerで画面遷移する場合

①ストーリーボードを追加する(今回、ファイル名はStoryboard.storyboard)

②identity inspectorで、対応するViewControllerとStoryboard ID を設定する。

f:id:ichi6161:20180107000615p:plain

③コードを追加

//定数にストーリーボードのファイル名を指定
let storyboard: UIStoryboard = UIStoryboard(name: "Storyboard", bundle: nil)

//ここで、ストーリーボードとViewControllerを結びつけ
let next = storyboard.instantiateViewController(withIdentifier:"Storyboard") as?ToDoViewController
  
//画面遷移
self.navigationController?.pushViewController(next!, animated: true)

以上

Navigation Controller関係

ナビゲーションバーにボタンをつけたいとき

Bar Button Itemを選択して、Itemを置きたい場所にドロップすればいいだけ。「Bar Button Item」を選択することに注意

複数のストーリーボードでナビゲーションバーを使うとき

それぞれのストーリーボードでナビゲーションコントローラーを挿入する。