iOS App 勉強メモ

### メモ

### UISlider Seek
```swift
player?.seek(to: seekTime, completionHandler: { (completion: Bool) in
    print("ompletionです")
})
```
### safeAreaの取得方法

```swift
func getSafeAreaInsets(): UIEdgeInsets {
    if #available(iOS 11.0, *) {
        if let insets = UIApplication.shared.keyWindow?.safeAreaInsets {
            return insets
        }
    }
    // iOS11.0以下の場合
    return UIEdgeInsets.zero
}

```

### 動画の再生
AVPlayer

```swift
// 動画ファイルのURL
if let url = URL(string: "https://~~~") {
    // 生成
    let player = AVPlayer(url: url)
    // レイヤーの追加
    let playerLayer = AVPlayerLayer(player: player)
    playLayer.frame = self.frame
    self.layer.addSublayer(playerLayer)
    // 再生
    player.play()
}
```
### **TopLayoutGuide** は**<font color="DeepPink">Deprecated</font>**

~~topLayoutGuide~~ は **<font color="DeepPink">非推奨</font>**

**view.safeAreaLayoutGuide** を使用する

```
menuBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
```
[Document](https://developer.apple.com/documentation/uikit/uiviewcontroller/1621367-toplayoutguide)

## @escaping とは
以下の場合にクロージャーに@escapingをつける



1. クロージャーがプロパティとして保存される（強参照される）
1. クロージャーがメソッド内ですぐに実行されない（非同期である）

```swift
func fetchVideos(completion: @escaping ([Article]) -> ()) {
    guard let url = URL(string: "https://hoge.com/api/articles") else {
        return
    }  
    URLSession.shared.dataTask(with: url) { (data: Data?, response: URLResponse?, error: Error?) in
        guard error == nil else {
            print("データ取得エラー")
            return
        }
        guard let data = data else {
            print("データ empty...")
            return
        }
        var articles = [Article]()
        do {
            articles = try JSONDecoder().decode([Article].self, from: data)
        } catch let error {
            print("JSON パースエラー")
            print(error)
        }
        DispatchQueue.main.async {
            completion(videos)
        }
    }.resume()
}

```
<参考>
[swiftでクロージャーに@escapingをつける場合を調べてみた](http://www.kuma-de.com/blog/2017-10-18/7381)

## layoutIfNeeded()
呼ばれたViewとその配下のViewで更新するViewがある場合は即座にViewを更新する

```swift

self.horizontalBarLeftAnchorContraint?.constant = x

UIView.animate(withDuration: 0.75, delay: 0, usingSpringWithDamping: 1, initialSpringVelocity: 1, options: .curveEaseOut, animations: {
    
  self.layoutIfNeeded()
  
}, completion: nil)
```


> Use this method to force the view to update its layout immediately. When using Auto Layout, the layout engine updates the position of views as needed to satisfy changes in constraints. Using the view that receives the message as the root view, this method lays out the view subtree starting at the root. If no layout updates are pending, this method exits without modifying the layout or calling any layout-related callbacks.

> ビューを強制的にレイアウトに強制的に更新するには、このメソッドを使用します。 自動レイアウトを使用する場合、レイアウトエンジンは、制約の変更を満たすために必要に応じてビューの位置を更新します。 このメソッドは、メッセージをルートビューとして受け取るビューを使用して、ルートから始まるビューサブツリーをレイアウトします。 保留中のレイアウト更新がない場合、このメソッドはレイアウトを変更せずに、またはレイアウト関連のコールバックを呼び出すことなく終了します。

[Document](https://developer.apple.com/documentation/uikit/uiview/1622507-layoutifneeded)
[setNeedsDisplay・setNeedsLayout・layoutIfNeeded・layoutSubviewsの違い](https://qiita.com/h1d3mun3/items/467c9a16d30b5de73969)

## NSLayoutAnchorの使い方、制約の作り方

```swift

barView.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 1/4).isActive = true
```
[iOS 9で追加されたNSLayoutAnchor](https://qiita.com/yucovin/items/4bebcc7a8b1088b374c9)

## 画面を下方向にスクロールさせた時だけNavigationBarを非表示にしたい
```swift
navigationController?.hidesBarsOnSwipe = true
```

[UITableViewをスクロールしたときに良い感じにNavigationBarを非表示にしたい](https://qiita.com/nextfactory/items/973369b39e1ba872b745)

## NSAttributedStringKey.foregroundColor

```
navigationController?.navigationBar.titleTextAttributes = [
    NSAttributedStringKey.foregroundColor: UIColor.white
]
```

## NSStringDrawingOptions
> Constants for the rendering options for a string when it is drawn.

[Document](https://developer.apple.com/documentation/uikit/nsstringdrawingoptions)

### **usesFontLeading**
> Uses the font leading for calculating line heights.
> 行の高さの計算に使用するフォントを使用します。

```
let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
```

### **usesLineFragmentOrigin**

>The specified origin is the line fragment origin, not the baseline origin. 
> 指定された起点は、線分の起点であり、ベースライン起点ではありません。
[Document](https://developer.apple.com/documentation/foundation/nsstring/nsstringdrawingoptions/1534956-useslinefragmentorigin)

## zero
> The rectangle whose origin and size are both zero.



```
static var zero: CGRect { get }
```
```

### usesLineFragmentOrigin
Discussion
The zero rectangle is equivalent to one created by calling CGRect(x: 0, y: 0, width: 0, height: 0).
```
[Document](https://developer.apple.com/documentation/coregraphics/cgrect/1455437-zero)

###`UIScreen.main.bounds`

ステータスバーを含む領域を返す


### key window

iOSでは、基本的にメインウィンドウのみがkey windowになれる
OSXでは、複数のウィンドウの中にkey windowと呼ばれるウィンドウが1つだけ存在し、イベントハンドリングを行う仕組みになっている

```
Q. key windowとは?

-> The app's key window

-> This property holds the UIView object in the windows array that is most recently sent the markeKeyAndVisible() message
```
```
var windows: [UIWindow]

-> The app's visible and hidden windows.
```

[Document](https://developer.apple.com/documentation/uikit/uiapplication/1622924-keywindow)


### ``` window?.makeKeyAndVisible() ```
shows the window and make it the key window

-> This is a convenience method to show current window and position it in front of all other windows at the same level or lower. If you only want to show the window, changes its isHidden property to false

[Document](https://developer.apple.com/documentation/uikit/uiwindow/1621601-makekeyandvisible)




### AutoLayout を解除する
```
translatesAutoresizingMaskIntoConstraints = false
```

例
```
let textView = UITextView()
textView.translatesAutoresizingMaskIntoConstraints = false
```

## 丸いアイコンを作る時
```
let imageView = UIImageView(name: "写真ファイル名")
imageView.layer.cornerRadius = 22
imageView.layer.maskToBounds = true
```

### ``` imageView.layer.maskToBounds ```とは???
はみ出して描画するか否か
TRUE -> はみ出さない
FALSE-> はみ出して描画

>When the value of this property is true, Core Animation creates an implicit clipping mask that matches the bounds of the layer and includes any corner radius effects. If a value for the mask property is also specified, the two masks are multiplied to get the final mask value.

Google 翻訳
> このプロパティの値がtrueの場合、コアアニメーションはレイヤの境界に一致する暗黙のクリッピングマスクを作成し、コーナー半径エフェクトを含みます。 maskプロパティの値も指定されている場合は、2つのマスクが乗算されて最終マスク値が取得されます。
The default value of this property is false.


[Document](https://developer.apple.com/documentation/quartzcore/calayer/1410896-maskstobounds)



## ``` textContainerInset ```


マージンを設定する

```例
let textView = UITextView()
textView.text = "テキストです"
textView.textContainerInset = UIEdgeInsetsMake(0, -4, 0, 0)
```

> This property provides text margins for text laid out in the text view. By default the value of this property is (8, 0, 8, 0).

[Document](https://developer.apple.com/documentation/uikit/uitextview/1618619-textcontainerinset)


### `navigationBar.isTranslucent`

ナビゲーションバーを透過にするかどうかの値を設定できる
デフォルト値は、**<font color="DeepPink">true</font>**

> A Boolean value indicating whether the navigation bar is translucent (true) or not (false).



[Document](https://developer.apple.com/documentation/uikit/uinavigationbar/1624928-istranslucent)


```例
navigationController?.navigationBar.isTranslucent = false

```

## 参考URL

[masksToBounds](https://qiita.com/shoheiyokoyama/items/c466383464d4b8f02936)