Yumico’s blog

iOS開発ブログ

iOS11に対応したらNavigationBarが・・・

Xcode9をダウンロードして意気揚々とアプリをビルド。
するとなんと、NavigationItemのtitleViewにセットしたViewの幅が小さくなって真ん中によっているではないか!

タイトルとボタンが被ってしまって焦ったけど、StackOverFlowで解決方法が見つかった。 titleViewにセットする側のUIViewにintrinsicContentSizeをoverrideするだけで解決。

override var intrinsicContentSize: CGSize {
   return CGSize(width: CGFloat.greatestFiniteMagnitude, height: self.frame.height)
}

よかったよかった。

【参考】

stackoverflow.com

swift3.0: Arrayの中身をソートする。

Arrayの中身が独自クラスの場合のソート方法

class Item: NSObject {
    var id: String = ""
    var itemName: String = ""
}

class data: NSObject {
    func prepareItem() {
        ///ソートするためのデータを用意する
        var list: [Item] = []
        let item1: Item = Item()
        item1.id = "id_a"
        item1.itemName = "aaa"
        list.append(item1)
        let item2: Item = Item()
        item2.id = "id_b"
        item2.itemName = "bbb"
        list.append(item2)
        let item3: Item = Item()
        item3.id = "id_c"
        item3.itemName = "ccc"
        list.append(item3)
        
        ///ソート用のデータlistをソートする(昇順)
        let ascending : [Item] = list.sorted(by: {$0.itemName < $1.itemName})
        ///ソート用のデータlistをソートする(降順)
        let descending: [Item] = list.sorted(by: {$0.itemName > $1.itemName})
    }
}

結局、仕事にするなら好きな事より得意な事を選ぶべし。

得意な事をやる

人より上達が早い!

褒められる。頼られる!!

嬉しいから頑張る!!!

もっと上達する!!!!

もっと褒められる。頼られる!!!!!




そして出世する。もちろん給料アップ!

嬉しいから頑張る!!



こんなにも素晴らしい循環があるだろうか!

UIViewを曲線上にアニメーションさせる方法

今回は半径分だけアニメーションさせて見ます。 f:id:Yumico:20170116191902g:plain

まずは全コードを。。
開発環境:Xcode8 + swift3
スタートボタンのイベントはIBかストーリーボードで設定して繋げてください。

import UIKit

class CurveAnimationViewController: UIViewController {

    let animateView: UIView = UIView()
    let viewSize: CGFloat = 100.0
    let curcleRadius: CGFloat = 150.0
    let duration: TimeInterval = 0.5
    var isDownView: Bool = false
    
    override func viewDidLoad() {
        super.viewDidLoad()
        animateView.frame = CGRect(x: (UIScreen.main.bounds.width / 2) - (viewSize / 2), y: UIScreen.main.bounds.height / 2 - viewSize / 2, width: viewSize, height: viewSize)
        animateView.layer.cornerRadius = viewSize / 2.0
        animateView.backgroundColor = UIColor.orange
        self.view.addSubview(animateView)      
    }
    
    @IBAction func tappedStartButton(_ sender: UIButton) {
        isDownView = !isDownView
        if isDownView {
            self.downAnimation()
        }else{
            self.upAnimation()
        }
    }
}


//MARK: - animation
extension CurveAnimationViewController {
    
    func downAnimation() {
        animateView.layer.removeAnimation(forKey: "end")
        let animation: CAKeyframeAnimation = self.animation()
        let path: CGMutablePath = CGMutablePath()      
        let startPoint: CGPoint = CGPoint(x: animateView.frame.minX + (animateView.frame.width / 2.0), y: animateView.frame.minY + (animateView.frame.height / 2.0))
        let midPoint: CGPoint = CGPoint(x: startPoint.x + curcleRadius, y: startPoint.y + curcleRadius / 2.0)
        let endPoint: CGPoint = CGPoint(x: startPoint.x, y: startPoint.y + curcleRadius)
        
        path.move(to: startPoint)
        path.addQuadCurve(to: endPoint, control: midPoint)
        animation.path = path
        animateView.layer.add(animation, forKey: "start")
    }
    
    func upAnimation() {
        animateView.layer.removeAnimation(forKey: "start")
        let animation: CAKeyframeAnimation = self.animation()
        let path: CGMutablePath = CGMutablePath()
        let startPoint: CGPoint = CGPoint(x: animateView.frame.minX + (animateView.frame.width / 2.0), y: animateView.frame.minY + (animateView.frame.height / 2.0) + curcleRadius)
        let midPoint: CGPoint = CGPoint(x: startPoint.x + curcleRadius, y: startPoint.y - curcleRadius / 2.0)
        let endPoint: CGPoint = CGPoint(x: animateView.frame.minX + (animateView.frame.width / 2.0), y: startPoint.y - curcleRadius)
        
        path.move(to: startPoint)
        path.addQuadCurve(to: endPoint, control: midPoint)
        animation.path = path
        animateView.layer.add(animation, forKey: "end")
    }

    func animation() -> CAKeyframeAnimation {
        let animation: CAKeyframeAnimation = CAKeyframeAnimation(keyPath: "position")
        animation.fillMode = kCAFillModeForwards
        animation.isRemovedOnCompletion = false
        animation.duration = duration
        return animation
    }
}

詳しく説明をしていきます。
今回はUIViewをアニメーションさせるためにCAKeyframeAnimationを使用しています。
func animation() -> CAKeyframeAnimation内で設定している内容は下記の通りです。

CAKeyframeAnimation 説明
fillMode アニメーションの再生中もしくは再生後のスタイル。 プロパティについてはこちらのサイトがわかりやすくまとめていました。【iOS Swift アニメーション入門 #4】Core AnimationのfillModeプロパティ | Swift,Objective-Cプログラミング ~ iOS ~
isRemovedOnCompletion アニメーション完了時に、ターゲットのレイヤーからアニメーションを削除するかどうかを設定。デフォルトはYes
duration アニメーションの長さ。

このCAKeyframeAnimationに作成したパスを入れて、動かしたいUIViewのレイヤーに加えてあげればアニメーションが開始されます。
では、パスをどのように設定しているか見ていきしょう。

let path: CGMutablePath = CGMutablePath()
//出発地点 > 動かしたいViewのセンターを計算しています。
let startPoint: CGPoint = CGPoint(x: animateView.frame.minX + (animateView.frame.width / 2.0), y: animateView.frame.minY + (animateView.frame.height / 2.0) + curcleRadius)
//中間地点 > 出発地点と最終地点の真ん中の位置を計算します。
let midPoint: CGPoint = CGPoint(x: startPoint.x + curcleRadius, y: startPoint.y - curcleRadius / 2.0)
//最終地点 > 最終地点のポジション。
let endPoint: CGPoint = CGPoint(x: animateView.frame.minX + (animateView.frame.width / 2.0), y: startPoint.y - curcleRadius)
        
//出発地点のポイントを設定します。
path.move(to: startPoint)
//最終地点と中間地点を設定します。
path.addQuadCurve(to: endPoint, control: midPoint)
//先ほどのCAKeyframeAnimationにパスを設定。
animation.path = path
//UIViewにCAKeyframeAnimationを追加。
animateView.layer.add(animation, forKey: "start")

pathの数値を変えるなどして試して見てください。
特に難しい計算を必要とせずに、どこに向かってアニメーションさせたいかのポイントを入れるだけなので、とても簡単に実装できます。

CocoaPods:ライブラリを追加する

すでにあるPodfileに、他のライブラリをさらに追加してインストールしたい。
そんな時も、初めてPodfileに書いたライブラリをインストールする時も、インストールする時はどんな時も $ pod install を使おう!
間違っても $ pod update もしくは $ pod update [PODNAME] は使わない。
なぜか?それは、update と install の違いを見ると明らかです。
※わりと $ pod update を使えと書いてある記事が多いので注意してください。

$ pod install

Podfileに書かれたライブラリをプロジェクトにインストールします。
Podfileに新しく追記されたライブラリだけをインストールするので、すでにインストール済みのライブラリは何も変化しません。
ただしPodfileから削除したライブラリはアンインストールされます。

$ pod update

すでにインストールされているライブラリのバージョンをアップデートします。
インストール済みのライブラリとPodfileに新しく記述したバージョン(バージョン指定していない時は、最新のバージョン)が異なっている場合、アップデートを開始します。
pod nameを指定していないと全てのライブラリが更新されてしまいますので注意が必要です。

ちなみに・・・

Podfileが置かれているディレクトリにPodfile.lockというファイルがあります。
このPodfile.lockというファイルにはインストールしたライブラリのバージョン情報が書かれおり、$ pod update した時にはこのファイルを見てアップデートをする必要があるかどうかを判別しています。

詳しくは本家サイトにも書かれていますので、参考にしてください。
guides.cocoapods.org

初めてCocoaPodsを導入する方は、下記の記事がとても分かりやすかったのでオススメです。
qiita.com

UINavigationControllerを使わない時のナビゲーションバーがステータスバーに被らない件。

タイトルがわかりにくくてごめんなさい。
つまり、こういうことデス。
f:id:Yumico:20161202172439p:plain:w500

はい、とてもかっこ悪いので修正していきます。
いつも通り完コピ用ソースです。
開発環境:Xcode8 + swift3

import UIKit

class ViewController: UIViewController,UINavigationBarDelegate {
    @IBOutlet weak var navigationBar: UINavigationBar!
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        navigationBar.delegate = self
    }

    func position(for bar: UIBarPositioning) -> UIBarPosition {
        return .topAttached
    }
}

やっていることは簡単で、UINavigationBarDelegateのfunc position(for bar: UIBarPositioning) -> UIBarPositionを実装するだけ。 戻り値は.topAttached
navigationBar.delegate = selfを忘れずに。。

f:id:Yumico:20161202172641p:plain:w500