しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

Sketchでハートを描いてみる

こちらのイラストレータ記事を参考にハートを描いてみました。
Sketchはv43.2を使っています。

magnets.jp

文字からハートを作る

まずはテキストでハートをセットします。

f:id:llcc:20171026130308p:plain

それを右クリックして「Convert to Outlines」を選びます。

f:id:llcc:20171026130435p:plain

以上でアウトライン化は完了です。
パスを自由に変形できるようになりました。

f:id:llcc:20171026130603p:plain

線からハートを作る

まずは四角形を描きます。

f:id:llcc:20171026131854p:plain

次に右上のパスをDeleteボタンで削除します。

f:id:llcc:20171026131921p:plain

三角形ができるので、一番長い辺の真ん中にパスを追加します。

f:id:llcc:20171026131957p:plain

作ったパスを左下に移動して、線の太さも大きくします。

f:id:llcc:20171026132048p:plain

次は線を丸くします。

f:id:llcc:20171026132158p:plain

最後に角度と高さを調整すれば完成です。

f:id:llcc:20171026132306p:plain

こちらはメニューのLayerからアウトライン化できます。

f:id:llcc:20171026132331p:plain

ペンツールでハートを作る

まずはVectorを使って半分のハートを描きます。

f:id:llcc:20171026132750p:plain

あとはそれをコピーして反転すれば完成です。

f:id:llcc:20171026132849p:plain

【Swift4】SpringIndicatorでおしゃれローディング

ローディング表示をオシャレにしたくて、SpringIndicatorというライブラリを試してみました。

github.com

f:id:llcc:20171025153537g:plain

インストール

いつものようにCocoaPodsでインストールします。

target 'MyApp' do
  use_frameworks!

  pod "SpringIndicator"
end

実装

実装はとても簡単で、SpringIndicatorを初期化してviewに貼り付けるだけです。

import UIKit
import SpringIndicator

class ViewController: UIViewController {
    override func viewDidLoad() {
        let indicator = SpringIndicator(frame: CGRect(origin: view.center, size: CGSize(width: 100, height: 100)))
        view.addSubview(indicator)
        indicator.start()
    }
}

f:id:llcc:20171025153537g:plain

線の太さや色を変えることができます。

let indicator = SpringIndicator(frame: CGRect(origin: view.center, size: CGSize(width: 100, height: 100)))
indicator.lineWidth = 5
indicator.lineColor = .brown

lineColorsをセットすると、1週ごとに色が変化して面白いです。

let indicator = SpringIndicator(frame: CGRect(origin: view.center, size: CGSize(width: 100, height: 100)))
indicator.lineColors = [.red, .purple, .blue, .purple]

回転速度も変更可能です。

let indicator = SpringIndicator(frame: CGRect(origin: view.center, size: CGSize(width: 100, height: 100)))
indicator.rotationDuration = 4.0

Reachability.swiftで通信状況を確認する

Reachability.swiftというライブラリで現在の通信状況を調べてみました。

Reachability.swiftのインストール

インストールはCocoaPodsで行いました。

target 'MyApp' do
  use_frameworks!

  pod 'ReachabilitySwift'
end

通信状況を確認する

Wifi/キャリア通信/電波なし は下のように確認できます。

import UIKit
import Reachability

class ViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        if let reachability = Reachability() {
            print(reachability.connection == .wifi)
            print(reachability.connection == .cellular)
            print(reachability.connection == .none)
        }
    }
}

通信可能になった時に通知する

whenReachableを使えば、通信可能になったタイミングを知ることができます。

let reachability = Reachability()
reachability?.whenReachable = { reachability in
    print(reachability.connection)
}
try? reachability?.startNotifier()

逆に通信できなくなったタイミングを知りたい時はwhenUnreachableを使います。

let reachability = Reachability()
reachability?.whenUnreachable = { reachability in
    print(reachability.connection)
}
try? reachability?.startNotifier()

この時、Reachabilityはインスタンス変数にするなどして開放されないよう気をつける必要があります。

import UIKit
import Reachability

class ViewController: UIViewController {
    let reachability = Reachability()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        reachability?.whenReachable = { reachability in
        }
        try? reachability?.startNotifier()
    }
}

通信状況が変わった時の通知は、NotificationCenterで検知する事もできます。

import UIKit
import Reachability

class ViewController: UIViewController {
    let reachability = Reachability()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        NotificationCenter.default.addObserver(self, selector: #selector(self.reachabilityChanged), name: .reachabilityChanged, object: reachability)
        try? reachability?.startNotifier()
    }
    
    @objc func reachabilityChanged() {
        print(Reachability()?.connection)
    }
}

Admobのネイティブアドバンス広告を試してみる

Admobのネイティブアドバンス広告というフォーマットを試してみました。
これは他社でよくあるネイティブ同様、渡された文字列や画像で広告画面を作っていくもののようです。

ネイティブアドバンス広の広告ユニット作成

まずはAdmobの画面から広告ユニットを作成します。
下のネイティブを選択して、「ネイティブ広告アドバンスに切り替える」リンクをクリックします。

注) こちらのリンクですが、2017/10/23現在アカウントによって出たり出なかったりしているようです。
もしかすると一部ユーザーにしか開放されていないのかもしれません。

f:id:llcc:20171023152841p:plain

切り替えたら広告の種類を選んで作成完了です。

f:id:llcc:20171023153140p:plain

ネイティブアドバンス広告の実装

まずはCocoaPodsでAdmobをインストールします。

target 'MyApp' do
  use_frameworks!

  pod 'Google-Mobile-Ads-SDK'
end

ネイティブアドバンス広告のデータ取得は下の通りです。
adUnitIDは先程登録したものを利用してください。

import UIKit
import GoogleMobileAds

class ViewController: UIViewController {
    var adLoader: GADAdLoader?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        adLoader = GADAdLoader(adUnitID: "AD UNIT ID", rootViewController: self, adTypes: [.nativeAppInstall], options: nil)
        adLoader?.delegate = self
        adLoader?.load(GADRequest())
    }
}

extension ViewController: GADNativeAppInstallAdLoaderDelegate {
    func adLoader(_ adLoader: GADAdLoader, didReceive nativeAppInstallAd: GADNativeAppInstallAd) {
        
    }
    
    func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: GADRequestError) {
        
    }
}

Delegateメソッドでは、広告のタイトル・アイコン・本文などが渡されるので、それを使って広告を組み立てます。

extension ViewController: GADNativeAppInstallAdLoaderDelegate {
    func adLoader(_ adLoader: GADAdLoader, didReceive nativeAppInstallAd: GADNativeAppInstallAd) {
        nativeAppInstallAd.headline // → タイトル
        nativeAppInstallAd.body // → 説明文
    }
    
    func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: GADRequestError) {
        
    }
}

実際の広告表示はXibファイルを利用します。

f:id:llcc:20171023173501p:plain

Xibファイルを作り、そのViewをGADNativeAppInstallAdViewにします。

f:id:llcc:20171023173536p:plain

その上にラベルを配置して、GADNativeAppInstallAdViewのheadlineViewなど、各プロパティーに紐付けていきます。

f:id:llcc:20171023173730p:plain

ここまで終わったら、Xibを使って広告を表示します。
下では、Xibを読み込んでheadlineとcallToActionをセットしています。

extension ViewController: GADNativeAppInstallAdLoaderDelegate {
    func adLoader(_ adLoader: GADAdLoader, didReceive nativeAppInstallAd: GADNativeAppInstallAd) {
        let adView = Bundle.main.loadNibNamed("View", owner: self, options: nil)?.first as! GADNativeAppInstallAdView
        adView.backgroundColor = UIColor.lightGray
        adView.frame = CGRect(x: 0, y: view.frame.height - 50, width: view.frame.width, height: 50)
        adView.nativeAppInstallAd = nativeAppInstallAd
        view.addSubview(adView)
        
        (adView.headlineView as? UILabel)?.text = nativeAppInstallAd.headline
        (adView.callToActionView as? UILabel)?.text = nativeAppInstallAd.callToAction
    }
    
    func adLoader(_ adLoader: GADAdLoader, didFailToReceiveAdWithError error: GADRequestError) {
        
    }
}

実行すると広告を表示する事ができます。
ラベルをタップすればAppStoreのページに遷移します。

f:id:llcc:20171023173851p:plain

今回は試してないのですが、広告タイプはインストール型以外にもあるようです。

GAD_EXTERN GADAdLoaderAdType const kGADAdLoaderAdTypeNativeAppInstall;
GAD_EXTERN GADAdLoaderAdType const kGADAdLoaderAdTypeNativeContent;
GAD_EXTERN GADAdLoaderAdType const kGADAdLoaderAdTypeNativeCustomTemplate;
GAD_EXTERN GADAdLoaderAdType const kGADAdLoaderAdTypeDFPBanner;

iPhoneアプリリリース時の「輸出コンプライアンス」のチェックを省く方法

iTunesConnectから審査に提出する際、「輸出コンプライアンス」と「広告ID」についてチェックをする必要があります。
毎回入力するのが手間だったので、省略する方法はないか調べてみました。

f:id:llcc:20171022154040p:plain

調べたところ、「輸出コンプライアンス」はInfo.plistにITSAppUsesNonExemptEncryptionを入れれば省略できるようです。

f:id:llcc:20171022154146p:plain

試したところ「輸出コンプライアンス」が表示されなくなりました。

f:id:llcc:20171022153716p:plain

objc_getAssociatedObjectで既存オブジェクトにプロパティーを追加

objc_getAssociatedObjectを使ってUIViewに新しいプロパティーを生やしてみました。

UIViewにプロパティーを追加する

UIViewにvalueというプロパティーを生やします。
実装は簡単で、下のようなextensionを追加すれば完了です。

private var valueKey = 0
extension UIView {
    var value: Int? {
        get {
            return objc_getAssociatedObject(self, &valueKey) as? Int
        }
        set {
            objc_setAssociatedObject(self, &valueKey, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
}

実行すると、下のように値をセットする事ができます。

let view = UIView()
print(view.value) // → nil
view.value = 10
print(view.value) // → Optional(10)

もちろんインスタンスが違えばプロパティーも別です。

let view = UIView()
let view2 = UIView()
view.value = 10
print(view.value) // → Optional(10)
print(view2.value) // → nil

キーとして宣言したvalueKeyですが、型はInt以外でも問題ありません。

private var valueKey = "valueKey"
extension UIView {
    var value: Int? {
        get {
            return objc_getAssociatedObject(self, &valueKey) as? Int
        }
        set {
            objc_setAssociatedObject(self, &valueKey, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
}

valueKeyの値は他プロパティーと被っても問題ありません。

private var valueKey = "valueKey"
private var valueKey2 = "valueKey"
extension UIView {
    var value: Int? {
        get {
            return objc_getAssociatedObject(self, &valueKey) as? Int
        }
        set {
            objc_setAssociatedObject(self, &valueKey, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
    var value2: Int? {
        get {
            return objc_getAssociatedObject(self, &valueKey2) as? Int
        }
        set {
            objc_setAssociatedObject(self, &valueKey2, newValue, .OBJC_ASSOCIATION_ASSIGN)
        }
    }
}

let view = UIView()
print(view.value) // → nil
print(view.value2) // → nil
view.value = 10
print(view.value) // → Optional(10)
print(view.value2) // → nil

UICollectionViewの並び替え

UICollectionViewでの並び替えを試してみました。

f:id:llcc:20171020143248p:plain

Storyboardを使わないでUICollectionViewを表示

まずは普通にUICollectionViewを表示してみます。
コードは下の通りです。

class CollectionViewController: UICollectionViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        collectionView?.register(UICollectionViewCell.self, forCellWithReuseIdentifier: "Cell")
        collectionView?.backgroundColor = UIColor.white
    }
    
    override func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 2
    }
    
    override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return 5
    }
    
    override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Cell", for: indexPath)
        cell.backgroundColor = UIColor.lightGray
        
        return cell
    }
}

CollectionViewのレイアウトは下の通りです。

let layout = UICollectionViewFlowLayout()
layout.itemSize = CGSize(width: 100, height: 100)
layout.minimumLineSpacing = 10
layout.sectionInset = UIEdgeInsets(top: 20, left: 0, bottom: 0, right: 0)

実行すると下のようにCollectionViewが表示されます。

f:id:llcc:20171020134036p:plain

UICollectionViewの並び替え

UICollectionViewの並び替えはmoveItemAtを実装するだけで完了です。

class CollectionViewController: UICollectionViewController {
    override func collectionView(_ collectionView: UICollectionView, moveItemAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
        
    }
}

これで下のように並び替えをする事ができるようになります。

f:id:llcc:20171020143349p:plain