はじめに
Xcode 11.4 の Storyboard で表示される Objects についてまとめました。これでざっくり色々使えるはず!
Widgets
ラベルとかボタンをウィジェットとしてまとめました。
基本的には IB で設定可能ですがコードで設定する場合の簡易実装も書いてます。
Label
文字表示するだけのやつ。
簡易実装
1 2 3 4 5 6 7 8 |
@IBOutlet private weak var label: UILabel! { didSet { label.text = "Labelです" label.textColor = .systemGray2 label.textAlignment = .natural label.font = .systemFont(ofSize: 17) } } |
Button
ボタンはこれのみチェックボックスやラジオボタンは自前で作る必要がある。
背景画像・テキスト・アイコンを設定できる。テキストとアイコンは UIControl.State.selected
など状態毎に設定できる。
簡易実装
1 2 3 4 5 6 7 8 |
@IBOutlet private weak var button: UIButton! { didSet { button.setTitle("Button", for: .normal) button.setImage(UIImage(systemName: "link.circle"), for: .normal) button.setTitleColor(.link, for: .normal) button.addTarget(self, action: #selector(buttonTouchUpInside(_:)), for: .touchUpInside) } } |
アクションは UIControl.Event.touchUpOutside
など色々あるが touchUpInside
しか使ったことない。。。
Segmented Control
タブのようなやつ。
簡易実装
1 2 3 4 5 6 7 8 |
@IBOutlet private weak var segmentedControl: UISegmentedControl! { didSet { segmentedControl.setTitle("First", forSegmentAt: 0) segmentedControl.setTitle("Second", forSegmentAt: 1) segmentedControl.selectedSegmentIndex = 0 segmentedControl.addTarget(self, action: #selector(segmentedControlValueChanged(_:)), for: .valueChanged) } } |
insertSegment
, removeSegment
で動的に変更したりできる。
Text Field
テキストフィールド。イベントを受信したい場合はデリゲートを設定する。
細かい入力チェックをする場合は textField.addTarget(self, action: #selector(.didChangeText(_:)), for: .editingChanged)
を設定してイベント取得する必要があるが正確にやろうと思うと色々めんどくさい。。。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
@IBOutlet private weak var textField: UITextField! { didSet { textField.delegate = self // コードで設定する場合 textField.text = "" textField.clearButtonMode = .always textField.placeholder = "ココに入力" textField.borderStyle = .roundedRect textField.minimumFontSize = 17 textField.font = .systemFont(ofSize: 14) textField.textAlignment = .natural textField.textColor = .label } } |
デリゲート
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
extension Hoge: UITextFieldDelegate { /// 編集を開始するか設定するfalseなら開始しない func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool { print("textFieldShouldBeginEditing") return true } /// 編集開始後に呼ばれる func textFieldDidBeginEditing(_ textField: UITextField) { print("textFieldDidBeginEditing") } /// 編集を停止するか設定するfalseなら停止しない func textFieldShouldEndEditing(_ textField: UITextField) -> Bool { print("textFieldShouldEndEditing") return true } /// 編集終了時に呼ばれる func textFieldDidEndEditing(_ textField: UITextField) { print("textFieldDidEndEditing") } /// 編集終了時に呼ばれる func textFieldDidEndEditing(_ textField: UITextField, reason: UITextField.DidEndEditingReason) { print("textFieldDidEndEditing reason: \(reason)") } /// 指定のテキストを変更するかどうか設定する func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { print("textFieldShouldChangeCharactersIn range: \(range), replacementString: \(string)") return true } /// 選択を変更したときに呼ばれる func textFieldDidChangeSelection(_ textField: UITextField) { print("textFieldDidChangeSelection") } /// 現在のテキストを削除するか設定する func textFieldShouldClear(_ textField: UITextField) -> Bool { print("textFieldShouldClear") return true } /// Returnボタンの押下を処理するか設定する func textFieldShouldReturn(_ textField: UITextField) -> Bool { print("textFieldShouldReturn") textField.resignFirstResponder() return true } } |
Slider
スライダー。ステップ数を設定したい場合は自前で頑張る必要がある。
簡易実装
1 2 3 4 5 6 7 8 |
@IBOutlet private weak var slider: UISlider! { didSet { slider.maximumValue = 100 slider.minimumValue = 0 slider.value = 10 slider.addTarget(self, action: #selector(sliderValueChanged(_:)), for: .valueChanged) } } |
Switch
スイッチ!
簡易実装
1 2 3 4 5 6 7 |
@IBOutlet private weak var uiSwitch: UISwitch! { didSet { // コードで設定する場合 uiSwitch.isOn = true uiSwitch.addTarget(self, action: #selector(switchValueChanged(_:)), for: .valueChanged) } } |
Activity Indicator View
インジケーター。
簡易実装
1 2 3 4 5 6 7 8 |
@IBOutlet private weak var activityIndicatorView: UIActivityIndicatorView! { didSet { // コードで設定する場合 activityIndicatorView.startAnimating() activityIndicatorView.hidesWhenStopped = true activityIndicatorView.style = .medium } } |
Progress View
プログレスバー。タイマーとかで値を設定して使う。
1 2 |
// これで値設定 progressView.progress = 0.8 |
Stepper
ステッパー。ステップ数毎に増減する値を管理するやつ。使ったことないけど便利かも。
簡易実装
1 2 3 4 5 6 7 8 9 10 11 12 |
@IBOutlet private weak var stepper: UIStepper! { didSet { stepper.stepValue = 1 stepper.minimumValue = 0 stepper.maximumValue = 100 stepper.value = 0 stepper.wraps = false // 最大値 <=> 最小値に戻すかどうか stepper.autorepeat = true // 長押し stepper.isContinuous = true // 長押し時にイベント送信されるかどうか stepper.addTarget(self, action: #selector(stepperValueChanged(_:)), for: .valueChanged) } } |
Horizontal Stack View
横に View
を並べる場合に便利。トルツメもしてくれる!
簡易実装
1 2 3 4 5 6 7 8 |
@IBOutlet private weak var horizontalStackView: UIStackView! { didSet { horizontalStackView.axis = .horizontal horizontalStackView.spacing = 0 horizontalStackView.alignment = .fill horizontalStackView.distribution = .fillEqually } } |
Vertical Stack View
縦に View
を並べる場合に便利。トルツメもしてくれる!
簡易実装
1 2 3 4 5 6 7 8 |
@IBOutlet private weak var verticalStackView: UIStackView! { didSet { verticalStackView.axis = .vertical verticalStackView.spacing = 0 verticalStackView.alignment = .fill verticalStackView.distribution = .fillEqually } } |
Image View
画像を表示するためのやつ。
簡易実装
1 2 3 4 5 6 |
@IBOutlet private weak var imageView: UIImageView! { didSet { imageView.image = UIImage(systemName: "folder.fill") imageView.contentMode = .scaleAspectFit } } |
contentMode
を .scaleAspectFit
にするとアスペクト比を保って拡大縮小してくれる。
Text View
改行できるテキストフィールド。中にリンクを入れることもできる。
簡易実装
1 2 3 4 5 6 7 8 9 |
@IBOutlet private weak var textView: UITextView! { didSet { textView.delegate = self textView.text = "ココに入力" textView.font = .systemFont(ofSize: 14) textView.textAlignment = .natural textView.textColor = .label } } |
デリゲート
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
extension WidgetsViewController: UITextViewDelegate { /// 編集を開始するか設定するfalseなら開始しない func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { print("textViewShouldBeginEditing") return true } /// 編集を停止するか設定するfalseなら停止しない func textViewShouldEndEditing(_ textView: UITextView) -> Bool { print("textViewShouldEndEditing") return true } /// 編集開始後に呼ばれる func textViewDidBeginEditing(_ textView: UITextView) { print("textViewDidBeginEditing") } /// 編集終了時に呼ばれる func textViewDidEndEditing(_ textView: UITextView) { print("textViewDidEndEditing") } /// 指定のテキストを変更するかどうか設定する func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { print("textViewShouldChangeTextIn range: \(range), replacementText: \(text)") return true } /// テキストを変更時に呼ばれる func textViewDidChange(_ textView: UITextView) { print("textViewDidChange") } /// 選択を変更したときに呼ばれる func textViewDidChangeSelection(_ textView: UITextView) { print("textViewDidChangeSelection") } } |
プレースホルダーは自前で作る必要がある。。。
View
ただの View。
Xib ファイルを読み込む場合は下記のようにする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
final class CustomView: XibLoadView { } class XibLoadView: UIView { override public init(frame: CGRect) { super.init(frame: frame) loadNib() } public required init(coder aDecoder: NSCoder) { super.init(coder: aDecoder)! loadNib() } private func loadNib() { let nibName = String(describing: type(of: self)) let bundle = Bundle(for: type(of: self)) let view = bundle.loadNibNamed(nibName, owner: self, options: nil)?.first as! UIView view.frame = bounds view.translatesAutoresizingMaskIntoConstraints = true view.autoresizingMask = [.flexibleWidth, .flexibleHeight] addSubview(view) } } |
Xib のファイル名は CustomView.xib とし File's Owner に CustomView
を設定する。そうするとIBで Custom Class に CustomView
を設定すると CustomView.xib が表示されるようになる。
Search Bar
検索バー。iOS 13 からは searchBar.searchTextField
でテキストフィールドが取得できる。(value は禁止!)
1 2 3 4 5 6 7 8 9 10 11 12 |
@IBOutlet private weak var searchBar: UISearchBar! { didSet { searchBar.delegate = self searchBar.placeholder = "検索" searchBar.text = "" searchBar.barStyle = .default searchBar.searchBarStyle = .default searchBar.showsCancelButton = true searchBar.showsBookmarkButton = true searchBar.showsSearchResultsButton = true } } |
デリゲート
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 |
extension Hoge: UISearchBarDelegate { /// 編集を開始するか設定するfalseなら開始しない func searchBarShouldBeginEditing(_ searchBar: UISearchBar) -> Bool { print("searchBarShouldBeginEditing") return true } /// 編集開始後に呼ばれる func searchBarTextDidBeginEditing(_ searchBar: UISearchBar) { print("searchBarTextDidBeginEditing") } /// 編集を停止するか設定するfalseなら停止しない func searchBarShouldEndEditing(_ searchBar: UISearchBar) -> Bool { print("searchBarShouldEndEditing") return true } /// 編集終了時に呼ばれる func searchBarTextDidEndEditing(_ searchBar: UISearchBar) { print("searchBarTextDidEndEditing") } /// テキストを変更時に呼ばれる func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) { print("searchBarTextDidChange searchText: \(searchText)") } /// 指定のテキストを変更するかどうか設定する func searchBar(_ searchBar: UISearchBar, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { print("searchBarShouldChangeTextIn range: \(range), replacementText: \(text)") return true } /// 検索押下時に呼ばれる func searchBarSearchButtonClicked(_ searchBar: UISearchBar) { searchBar.resignFirstResponder() print("searchBarSearchButtonClicked") } /// ブックマーク押下時に呼ばれる func searchBarBookmarkButtonClicked(_ searchBar: UISearchBar) { searchBar.resignFirstResponder() print("searchBarBookmarkButtonClicked") } /// キャンセル押下時に呼ばれる func searchBarCancelButtonClicked(_ searchBar: UISearchBar) { searchBar.resignFirstResponder() print("searchBarCancelButtonClicked") } /// ResultsList押下時に呼ばれる func searchBarResultsListButtonClicked(_ searchBar: UISearchBar) { searchBar.resignFirstResponder() print("searchBarResultsListButtonClicked") } /// スコープボタンが押されてインデックスが変わった時に呼ばれる func searchBar(_ searchBar: UISearchBar, selectedScopeButtonIndexDidChange selectedScope: Int) { print("searchBarSelectedScopeButtonIndexDidChange selectedScope: \(selectedScope)") } } |
iOS 13 から色々新機能があるみたい(参考)
Pickers
ピッカー系まとめ。
Date Picker
日付選択用
簡易実装
1 2 3 4 5 6 7 8 9 |
@IBOutlet private weak var datePicker: UIDatePicker! { didSet { // コードで設定する場合 datePicker.date = Date() datePicker.datePickerMode = .dateAndTime datePicker.minuteInterval = 1 datePicker.addTarget(self, action: #selector(datePickerValueChanged(_:)), for: .valueChanged) } } |
Picker View
独自設定値選択用
簡易実装
1 2 3 4 5 6 |
@IBOutlet private weak var pickerView: UIPickerView! { didSet { pickerView.delegate = self pickerView.dataSource = self } } |
デリゲート
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
let pickerTitles: [[String]] = [["AAA", "BBB", "CCC"], ["EEE", "FFF", "GGG"]] extension Hoge: UIPickerViewDelegate { func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return pickerTitles[component][row] } // 選択時に呼ばれる func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { print("pickerViewDidSelectRow row: \(row), component: \(component)") } } extension Hoge: UIPickerViewDataSource { func numberOfComponents(in pickerView: UIPickerView) -> Int { return pickerTitles.count } func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { return pickerTitles[component].count } } |
Scroll
Scroll View
Content Layout Guide
がスクロール領域のガイドで Frame Layout Guide
がスクロール View の領域ガイドだと思う。
実装例では
ScrollView
の直下にStackView
(ContentView) を置く- ContentView の上下左右を
Content Layout Guide
に合わせる - ContentView の高さを
Frame Layout Guide
の高さに合わせる - ContentView 内の View の幅を
Frame Layout Guide
の幅に合わせる
Page Control
現在のページ位置を表示するためのやつ。スワイプアクションもつけれる。
簡易実装
1 2 3 4 5 6 7 8 |
@IBOutlet private weak var pageControl: UIPageControl! { didSet { pageControl.currentPage = 0 pageControl.numberOfPages = 9 pageControl.currentPageIndicatorTintColor = .systemOrange pageControl.pageIndicatorTintColor = .systemBlue } } |
横スクロールで Page Control
と ScrollView
を連動させるには下記のようにする。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
final class ScrollViewController: UIViewController { @IBOutlet private weak var pageControl: UIPageControl! { didSet { pageControl.currentPage = 0 pageControl.numberOfPages = 9 pageControl.currentPageIndicatorTintColor = .systemOrange pageControl.pageIndicatorTintColor = .systemBlue } } @IBOutlet private weak var scrollView: UIScrollView! { didSet { scrollView.isScrollEnabled = true scrollView.isPagingEnabled = true scrollView.showsHorizontalScrollIndicator = true scrollView.showsVerticalScrollIndicator = false scrollView.indicatorStyle = .default scrollView.delegate = self } } @IBAction private func pageControlValueChanged(_ sender: Any) { scrollPage(at: pageControl.currentPage) } private func scrollPage(at index: Int) { let x = scrollView.frame.size.width * CGFloat(index) scrollView.setContentOffset(.init(x: x, y: 0), animated: true) } } extension ScrollViewController: UIScrollViewDelegate { func scrollViewDidScroll(_ scrollView: UIScrollView) { pageControl.currentPage = Int(scrollView.contentOffset.x / scrollView.frame.size.width) } } |
Web
Web View (deprecated)
UIWebView
は完全に非推奨になりました!使わないようにしましょう!
新規アプリは 2020/4 まで
既存アプリは 2020/12 まで
WebKit View
ウェブページ表示用のやつ。
簡易実装
1 2 3 |
let url = URL(string: "https://www.am10.blog/?p=89")! let request = URLRequest(url: url) webView.load(request) |
openWindow とかは色々設定しないといけない。。。詳細は下記参考
単純に Web ページ表示したいだけなら SFSafariViewController
を検討してもいいかも。こいつも target="_blank"
が連続であると表示されなかったりするので注意
(参考)
下記のようにするとローカルの動画ファイルとか表示できる。
1 2 3 |
let url = Bundle.main.url(forResource: "sample", withExtension: "mov")! let request = URLRequest(url: url) webView.load(request) |
Containers
TableView, CollectionView, ContainerView のまとめ
Table View Cell
UITableView
のセル
Table View
リスト表示用の View。
簡易実装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
final class HogeViewController: UIViewController { @IBOutlet private weak var tableView: UITableView! { didSet { tableView.delegate = self tableView.dataSource = self // xibで実装したカスタムセルを使う場合 tableView.register(UINib(nibName: "Sample2TableViewCell", bundle: nil), forCellReuseIdentifier: "Sample2") } } } extension ContainersViewController: UITableViewDataSource { func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return tableDataList.count } func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { switch indexPath.row { case 0: // IB で カスタムセルに id を設定している場合 let cell = tableView.dequeueReusableCell(withIdentifier: "Sample1", for: indexPath) as! Sample1TableViewCell return cell case 1: // xibで実装したカスタムセルを使う場合 let cell = tableView.dequeueReusableCell(withIdentifier: "Sample2", for: indexPath) as! Sample2TableViewCell return cell default: // デフォルトセルを生成して使う場合(IB で id 設定しても使える) var cell = tableView.dequeueReusableCell(withIdentifier: "Cell") if cell == nil { cell = UITableViewCell(style: .default, reuseIdentifier: "Cell") } cell?.textLabel?.text = "Default Row: \(indexPath.row)" return cell! } } } extension ContainersViewController: UITableViewDelegate { func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { print("tableViewDidSelectRowAt indexPath: \(indexPath)") } } |
細かいのは下記参考にどうぞ。
セルは再利用する仕組みがあるので毎回 init
しないよう気をつけよう!(わりと重くなります)
Collection View Cell
UICollectionView
のセル
Collection Reusable View
UICollectionView
のセクション用の View
細かいのは下記参考
UICollectionViewのHeaderカスタマイズいろいろ
Collection View
グリッドなど複雑なリスト表示用の View。
簡易実装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
final class HogeViewController: UIViewController { @IBOutlet private weak var collectionView: UICollectionView! { didSet { collectionView.delegate = self collectionView.dataSource = self // xibで実装したカスタムセルを使う場合 collectionView.register(UINib(nibName: "Sample2CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "Sample2") } } } extension ContainersViewController: UICollectionViewDataSource { func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return collectionDataList.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { switch indexPath.row { case 0: // IBで実装したカスタムセルを使う場合 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Sample1", for: indexPath) as! Sample1CollectionViewCell // なにか設定処理 return cell default: // xibで実装したカスタムセルを使う場合 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Sample2", for: indexPath) as! Sample2CollectionViewCell // なにか設定処理 return cell } } func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView { let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "Header", for: indexPath) as! SampleCollectionHeader // なにか設定処理 return header } } extension ContainersViewController: UICollectionViewDelegate { func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) { print("collectionViewDidSelectRowAt indexPath: \(indexPath)") } } |
セルは再利用する仕組みがあるので毎回 init
しないよう気をつけよう!(わりと重くなります)
Container View
他の UIViewController
を埋め込む場合に使う。
簡易実装
1 2 3 4 5 6 7 8 9 10 11 12 13 |
final class HogeViewController: UIViewController { // これで取得可能 private var sampleContainerViewController: SampleContainerViewController { return children.first { $0 is SampleContainerViewController } as! SampleContainerViewController } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let destination = segue.destination as? SampleContainerViewController { // ここで初期化処理できる print(destination.hoge) } } } |
Navigation
Navigation Controller
画面を階層管理するためのやつ。push
で遷移できるようになる。戻るときは pop
で最初の画面や指定の画面に戻れる。push
も複数画面一気に設定することもできる。
Navigation Bar
画面上部のバー。通常は UINavigationController
と一緒に使う。
Navigation Item
UINavigationBar
のコンテンツを管理するやつ。leftBarButtonItem
, rightBarButtonItem
, titleView
などを持っている。
Toolbar
画面下部にボタンを配置したりするのに使うやつ。なかには UIBarButtonItem
を配置する。
Bar Button Item
ToolBar のボタン。画像か文字を表示できる。色を設定したい場合は tintColor
で設定する。
凝ったやつを表示したい場合は UIView
を作成して init(customView: UIView)
で突っ込んだりできる。
Fixed Space Bar Button Item
UIBarButtonItem
同士の固定の余白を設定する場合に使う。実体は UIBarButtonItem
。
Flexible Space Bar Button Item
UIBarButtonItem
を等間隔で並べたい場合とかに使う。両端にボタンを寄せたい場合は BarButtonItem
FlexibleSpaceBarButtonItem
UIBarButtonItem
とするといい。
実体は UIBarButtonItem
。
Tab
Tab Bar Controller
タブで画面遷移を管理するやつ。
それぞれの画面から別タブにコードで遷移する場合は下記のようにできる
1 2 3 4 |
guard let tabBarController = parent as? UITabBarController else { return } tabBarController.selectedViewController = tabBarController.viewControllers?[1] |
Tab Bar
タブのボタンを置くためのやつ。
Tab Bar Item
タブのボタン。テキストと画像を設定できる。画像のサイズは25*25(参考)
Image Set の設定の Render As を Original Image に設定すると画像を塗りつぶさずに表示できる。
Gestures
ジェスチャまとめ。ジェスチャの競合とかいい感じにするには下記参考。
よくわかるUIGestureRecognizerDelegate
Tap Gesture Recognizer
タップジェスチャ。指の本数とかタップ回数とか設定できる。
簡易実装
1 2 3 4 5 6 7 8 |
@IBOutlet private var tapGesture: UITapGestureRecognizer! { didSet { tapGesture.numberOfTouchesRequired = 1 tapGesture.numberOfTapsRequired = 1 tapGesture.buttonMaskRequired = .primary tapGesture.addTarget(self, action: #selector(tapGestureAction(_:))) } } |
Pinch Gesture Recognizer
ピンチイン・ピンチアウトのジェスチャ。scale
とかあるけどよくわからない。。。
簡易実装
1 2 3 4 5 6 |
@IBOutlet private var pinchGesture: UIPinchGestureRecognizer! { didSet { pinchGesture.scale = 1 pinchGesture.addTarget(self, action: #selector(pinchGestureAction(_:))) } } |
Rotation Gesture Recognizer
回転ジェスチャ(2本指で回転させるやつ??)。rotation
の設定と取得ができる。(あんま使い方わかってない。。。)
簡易実装
1 2 3 4 5 6 |
@IBOutlet private var rotationGesture: UIRotationGestureRecognizer! { didSet { rotationGesture.rotation = 0 rotationGesture.addTarget(self, action: #selector(rotationGestureAction(_:))) } } |
Swipe Gesture Recognizer
スワイプジェスチャ。方向と指の本数とかが設定できる。
1 2 3 4 5 6 7 |
@IBOutlet private var swipeGesture: UISwipeGestureRecognizer! { didSet { swipeGesture.direction = .right swipeGesture.numberOfTouchesRequired = 1 swipeGesture.addTarget(self, action: #selector(swipeGestureAction(_:))) } } |
Pan Gesture Recognizer
パンジェスチャ(ドラッグ??)。指の本数の最大値・最小値とかを設定できる。
簡易実装
1 2 3 4 5 6 7 |
@IBOutlet private var panGesture: UIPanGestureRecognizer! { didSet { panGesture.minimumNumberOfTouches = 1 panGesture.maximumNumberOfTouches = Int.max panGesture.addTarget(self, action: #selector(panGestureAction(_:))) } } |
Screen Edge Pan Gesture Recognizer
画面の端のパンジェスチャ。Edges
の設定ができる。その他 UIPanGestureRecognizer
と同じ設定ができる。
簡易実装
1 2 3 4 5 6 |
@IBOutlet private var screenEdgePanGesture: UIScreenEdgePanGestureRecognizer! { didSet { screenEdgePanGesture.edges = .right screenEdgePanGesture.addTarget(self, action: #selector(screenEdgePanGestureAction(_:))) } } |
Long Press Gesture Recognizer
ロングプレスジェスチャ。有効最小秒数や指の本数とか設定できる。
簡易実装
1 2 3 4 5 6 7 8 9 |
@IBOutlet private var longPressGesture: UILongPressGestureRecognizer! { didSet { longPressGesture.minimumPressDuration = 0.5 longPressGesture.numberOfTouchesRequired = 1 longPressGesture.numberOfTapsRequired = 0 longPressGesture.allowableMovement = 10 longPressGesture.addTarget(self, action: #selector(longPressGestureAction(_:))) } } |
Custom Gesture Recognizer
カスタムのジェスチャ用。詳しくは下記見るといいかも。
マルチタッチイベントサンプル2 - カスタムGesture Recognizer
簡易実装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 |
/// 3本指のタップとパンジェスチャに反応する final class CustomGestureRecognizer: UIGestureRecognizer { private let fingers = 3 override func reset() { super.reset() state = .possible } override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) { super.touchesBegan(touches, with: event) if touches.count != fingers { state = .failed return } state = .began } override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent) { super.touchesMoved(touches, with: event) if state == .failed || touches.count != fingers { return } state = .changed } override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent) { super.touchesEnded(touches, with: event) if state == .failed { state = .failed return } state = .ended } override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent) { super.touchesCancelled(touches, with: event) state = .cancelled } } |
これを Custom Gesture Recognizer の Custom Class に設定する
Map Kit View
地図を表示するやつ。APIキーとかいらない!
ピン表示や現在値表示、目的地までへの道順表示など色々できる。詳しくは下記とか見るといいかも。
簡易実装
1 2 3 4 5 6 7 |
@IBOutlet private weak var mapView: MKMapView! { didSet { // 兵庫県明石市あたりを初期表示 let span = MKCoordinateSpan(latitudeDelta: 0.5, longitudeDelta: 0.5) mapView.region = MKCoordinateRegion(center: .init(latitude: 34.39, longitude: 135), span: span) } } |
なんか実機だと変なタイミングでクラッシュする
Xcode11.4でMKMapViewを使うとクラッシュするかもしれない
ViewControllers
ViewController
系のまとめ。
View Controller
通常の画面。
Storyboard Reference
他の Storyboard とつなぐためのやつ。他の Storyboard の ViewController に Segue をつなげたりできる。
Table View Controller
TableView
つきの ViewController。下記のように色々便利機能があるが固定ヘッダーとか TableView
以外も置きたい場合は向かないかも。
- tableViewのひも付けとかしなくてもいい
- var clearsSelectionOnViewWillAppear: Bool
- var refreshControl: UIRefreshControl?
- 編集モードの時に func setEditing(_ editing: Bool, animated: Bool) オーバーライドしなくてもいい
- キーボード表示時に自動でスクロールしてくれる
- static cell が使える
- セーフエリアまわりもなんかいい感じにしてくれる
Collection View Controller
CollectionView
つきの ViewController。 clearsSelectionOnViewWillAppear
くらいの利点しかないかも?(使ったことないのでよくわからない。。。)
Page View Controller
ページ管理してくれるやつ。上下や左右のスワイプでページ遷移できる。ページめくりのアニメーションもつけれる。電子書籍とかで便利かも?
簡易実装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 |
struct Page { let index: Int let color: UIColor } final class SamplePageViewController: UIViewController { @IBOutlet private weak var label: UILabel! var page: Page? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. if let page = page { label.text = "Page: \(page.index)" view.backgroundColor = page.color } } } final class PageViewController: UIPageViewController { private var currentPageIndex = 0 private var pages = [Page]() private let colors: [UIColor] = [ .systemRed, .systemBlue, .systemPink, .systemTeal, .systemGreen, .systemIndigo, .systemOrange, .systemYellow, .systemPurple ] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. for i in 0...16 { pages.append(.init(index: i, color: colors.shuffled()[0])) } setViewControllers([makeSamplePage(page: pages[currentPageIndex])], direction: .forward, animated: false) dataSource = self } private func makeSamplePage(page: Page) -> SamplePageViewController { let viewController = SamplePageViewController() viewController.page = page return viewController } } extension PageViewController: UIPageViewControllerDataSource { func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { if currentPageIndex == 0 { return nil } currentPageIndex -= 1 return makeSamplePage(page: pages[currentPageIndex]) } func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { if currentPageIndex >= pages.count - 1 { return nil } currentPageIndex += 1 return makeSamplePage(page: pages[currentPageIndex]) } } |
AVKit Player View Controller
簡単に動画再生とかできるやつ。
簡易実装
1 2 3 4 5 6 7 8 9 10 11 12 13 |
import UIKit import AVKit final class PlayerViewController: AVPlayerViewController { override func viewDidLoad() { super.viewDidLoad() let url = Bundle.main.url(forResource: "sample", withExtension: "mov") player = AVPlayer(url: url!) player?.play() } } |
Split View Controller
Master
と Detail
で分けて表示してくれるやつ。幅が十分ある場合は両方表示し、iPhone など幅が狭い場合は1画面ずつ表示したりできる。
Split (iPhone)
Master | Detail |
---|---|
iPad (LandScape)
簡易実装
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 |
final class SplitViewController: UISplitViewController { override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. delegate = self } } extension SplitViewController: UISplitViewControllerDelegate { func splitViewController(_ splitViewController: UISplitViewController, collapseSecondary secondaryViewController: UIViewController, onto primaryViewController: UIViewController) -> Bool { return true // collapseのときにMaster表示するようにする } } // UINavigationControllerのRootに設定 final class MasterViewController: UITableViewController { private let colors: [UIColor] = [ .systemRed, .systemBlue, .systemPink, .systemTeal, .systemGreen, .systemIndigo, .systemOrange, .systemYellow, .systemPurple ] private let tableDataList = [ "Red", "Blue", "Pink", "Teal", "Green", "Indigo", "Orange", "Yellow", "Purple" ] override func viewDidLoad() { super.viewDidLoad() } override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if let detail = segue.destination as? DetailViewController, let param = sender as? (color: UIColor, text: String) { detail.text = param.text detail.color = param.color } } @IBAction private func close(_ sender: Any) { dismiss(animated: true) } // MARK: - Table view data source override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return tableDataList.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) cell.textLabel?.text = tableDataList[indexPath.row] return cell } override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { performSegue(withIdentifier: "toDetail", sender: (color: colors[indexPath.row], text: tableDataList[indexPath.row])) } } final class DetailViewController: UIViewController { var color: UIColor? var text: String? @IBOutlet private weak var label: UILabel! override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. label.text = text view.backgroundColor = color } } |
細かい制御は色々工夫しないといけないけど iPad, iPhone で共通プロジェクトにしたい場合とかはわりと力を発揮するかも。(ほぼ使ったことないのであまり知らない。。。)
VisualEffect
磨りガラス効果をかけてくれる UIVisualEffectView
。
詳細はドキュメントで。。。
Visual Effect View with Blur
背後の View にエフェクトをかける。
こういう構成で中に View が入っている。
Visual Effect View with Blur and Vibrancy
子 View にエフェクトをかける。
こういう構成で中に UIVisualEffectView
が入っている。中の UIVisualEffectView
は Vibrancy
にチェックが入っている。
Object
NSObject
使ったことないのでどういうとき使うかわからない。。。
Menu (MacOS)
MacOS 用のメニュー関連のやつ。MacOS 用なのでざっくり説明。
Main Menu
ヘッダー部分。Application とか Window とかメニューを羅列するやつ。
Sub Menu
ヘッダー部分の要素。(Application とか Window とか)
Inline Section Menu
Sub Menu 内のセクション。
Menu Command
Sub Menu 内の要素。(Item 1 とか)
Inline Section Menu の下か Sub Menu 直下に置く。
使ったことなくて使い方わからないやつ
SceneKit View
SceneKit の SCNView
。SceneKitなのでたぶん 3D 関連のやつ。
Create 3D games and add 3D content to apps using high-level scene descriptions. Easily add animations, physics simulation, particle effects, and realistic physically based rendering.
ドキュメント
SpriteKit View
SpriteKit の SKView
。SpriteKit なので 2D ゲーム用のやつ??
Add high-performance 2D content with smooth animations to your app, or create a game with a high-level set of 2D game-based tools.
ドキュメント
Hosting View Controller
SwiftUI の View を管理するためのやつ。プロジェクト作成時に SwiftUI を選択すると window.rootViewController
に設定される。
A UIKit view controller that manages a SwiftUI view hierarchy.
GLKit View
GLKit の GLKView
。GLKit なので OpenGL 用のやつだと思う。
iOS 12 で Deprecated になってる。
Speed up OpenGL ES or OpenGL app development. Use math libraries, background texture loading, pre-created shader effects, and a standard view and view controller to implement your rendering loop.
ドキュメント
GLKit View Controller
GLKit の GLKViewController
。GLKView
がのっている。
iOS 12 で Deprecated になってる。
ドキュメント
A view controller that manages an OpenGL ES rendering loop.
ARKit SceneKit View
ARKit の ARSCNView
。SCNView
を継承した View で 2D の AR がやりたいときに使うやつだと思う。
A view that enables you to display an AR experience with SceneKit.
ARKit SpriteKit View
ARKit の ARSKView
。SKView
を継承した View で 3D の AR がやりたいときに使うやつだと思う。
A view that enables you to display an AR experience with SpriteKit.
RealityKit AR View
RealityKit の ARView
。ARKit と一緒に使って 3D 表示をするためのやつだと思う。
Simulate and render 3D content for use in your augmented reality apps.
ドキュメント
さいごに
これをみれば iOS 開発を忘れてもすぐに思い出せるかも!
Stepper
とか Gesture とか使ったことないのもポツポツあるけど便利そうなのも多い。
今回書けてないやつも今後追記するかも。。。 ARKit は使ってみたいと思ってるけどずっと使えてない。。。
Android のコンポーネントまとめもよかったらみてね。(未だ閲覧数0...\(^o^)/)
コメント