Swift3 TabのFrameを取得する

#Swift3 TabのFrameを取得する

もうすぐ、Xcode9の正式版がリリースされ、コード回収が必要な場合は、コードをリファクタリングしてアップデートしますが、現在ネットに題名のようなロジックがなかったので、Githubにソースをあげました。


https://github.com/daisukenagata/TabTapSample

#実装内容->TabBar

![Movie.gif](https://qiita-image-store.s3.amazonaws.com/0/131469/99ed7d4c-4589-ea9e-ff31-16729ea54165.gif)

Tabをタップした場合の位置を取得して、何かする。
今回はUIをUIBezierPath()メソッドで用意しましたが画像でもなんでも良いと思います。<-NavigationBarのロジックも追加しました！

#コードFlow

###1.AppDelegateでTabControllerの生成、StoryBoardも用意

###2.FirstViewControllerでTabControllerをデリゲート設定

class FirstViewController: UIViewController,UITabBarControllerDelegate 

override func viewDidLoad() {
        super.viewDidLoad()
        self.tabBarController?.delegate = self
 }

###3. タップされた場合のデリゲートメソッド
func tabBarController(_ tabBarController: UITabBarController,didSelect viewController: UIViewController)

###4.ここが取得ロジック
  var v = Array＜UIView＞()
        for view in tabBarController.tabBar.subviews {
            v.append(view)
            }
これでv.append(view)の下にprint(view.layer.debugDescription)を実装して
ログを見ると、(2 1; 76 48),(82 1; 76 48),(162 1; 76 48),(242 1; 76 48)と
値が取れてました。この値を元に引数や計算式を使い、表示座標を算出しています。

UIを計算するクラスにUIの型を渡しています。ここにCGRect情報が入っています。
viewGroval.views = PointDraw().drawPoint(view: v[tabBarController.selectedIndex+1], tab: tabBarController)

各TabのCGRectが取得できてしまえば、カスタム実装なら,制約なく大体できると思います。

###5.UIを描写するクラス
func drawPoint(view: UIView,tab:UITabBarController)->UIView 

4.で取得した、UIViewとUITabBarControllerを元にUIを計算しています。
  line.move(to: CGPoint(x: view.frame.origin.x+(view.frame.size.width/2), y: tab.tabBar.center.y-tab.tabBar.frame.size.height));
        line.addLine(to: CGPoint(x: (view.center.x-10), y: tab.tabBar.center.y-tab.tabBar.frame.size.height*3));
        line.addLine(to: CGPoint(x: (view.center.x+10), y: tab.tabBar.center.y-tab.tabBar.frame.size.height*3));


###6.初回にタップした時だけの挙動
 guard onlyOnce != false else {
            self.view.addSubview(viewGroval.views)
            onlyOnce = true
            return
        }
この実装をすることで、最初の一回のみ一番左SearchButtonが呼ばれます。

次回からは、viewDidAppearでaddSubしています。
このロジックをすることにより、同時押しの場合でも各一箇所のみ表示する挙動になりました。

理由を記載すると長くなるので、この部分は割愛いたします。

#実装内容->NavigationBar

![NaviMovie.gif](https://qiita-image-store.s3.amazonaws.com/0/131469/25d7e796-e805-3db1-293d-8a7be19ac6e1.gif)

NavigationBarのButtonをタップすると、ラベルの最終地点まで三角のラベルが移動します。

#コードFlow
###1. 起動のタイミング

Buttonのタイトル設定
self.naviButton.setTitle(GetTimerSet().getTimer(), for: UIControlState.normal)
サイズ調整
        self.naviButton.sizeToFit()
色設定
        self.naviButton.backgroundColor = UIColor.cyan


###2. NavigationBar押下

アニメーションを起こすサイズ設定
 AnimateImage().animateImage(target: pointLabel,frameWith:(self.naviButton.frame.origin.x+self.naviButton.frame.size.width)-(self.pointLabel.frame.size.width/2))

NavigationBarの始まりからNavigationBarの幅＋ラベル半分の幅を引いた値を渡しています。とても簡単ロジックです。

###3. Animateクラス

class AnimateImage: UIView ここで2.の値を計算してアニメーションを実施してます。

###4.現在時間の設定

class GetTimerSet:GetTimer ここで時間設定ロジックを実施してます。

protocolで設定した理由は2つあり、ViewController側でメソッドが見えると見やすい部分もあるかなと思い、設定しました。GetTimerSetクラスに設定するメソッドが複数ある場合に
ViewController側で作業しやすいと思います。方法は複数あるのですが、protocol系、Decode系、Encode系など、最近新しいロジックを書いていなかったので、ウォームアップに書きました。


#まとめ
[参考資料](https://l.facebook.com/l.php?u=https%3A%2F%2Fstackoverflow.com%2Fquestions%2F6325457%2Fgetting-the-frame-of-a-particular-tab-bar-item&h=ATM1GC6-rvspmcxDJuvap1pRIZ4yYmK7naEAMCGu1UQyRZ2yV9JJpoqnMclI93UkH3EAp4vht9qMhsDwGyVAxzYEGIXFO1iKQP3LzPU2MPzs7tKLO0QDPlf-FERpJsoymIci1qkwLu7vzw_3JAuZ4Vh8hgoLB9c9mLLIAvJcCoRIqUOSN_46QK2Tmgl_tJPueBOrWt7VrMQvZXk88mM7Vw7i1SElGfW1CyMgV8PUGoZdz09DvrBJ4pshQRpjHPIr-1whSqKVSEZytF5LqM39hf8mJ9xovGqoHgwu1DRx33GRBpsNzfgIRSp2vVNmE0y5mQ)
こちらの資料が参考になりました。

最近はMetalプログラミングを研究していますが、ネットにない情報や、Swift4について具体的なソースとともにアップデートしていきます。

今後共よろしくお願い致します。

貴重なお時間お読み頂き誠にありがとうございます。