元柔道整復師エンジニアBlog

- 元柔道整復師エンジニアBlog -

『 エンジニアをリングする。』

Info.plistのディレクトリ変更後のBuildPath設定について

Info.plistの階層を変更した後にBuildすると、以下のように発生する。

error: Build input file cannot be found: '/Users/username/***/Info.plist' (in target '***' from project '***')
Build input file cannot be found: '***/Info.plist'

そのため、Info.plistのディレクトリを変更した場合

Project Editor のBuild Settings > info.plist File を現在のInfo.plistファイルパスに変更すれば解消される。

例)Appというグループにinfo.plistを格納した場合
⇒ project名/App/info.plist

【Swift】TableViewCellの重複タップを防ぎたい(二度押し防止)

TableViewCellを複数回連続で選択した場合において、Cell選択時のイベント処理が複数回呼ばれてしまう。

前提

  • TableViewCellタップ時にVCへ遷移する。
  • tableView:didSelectRowAt内では、負荷の大きいサーバー通信後にVCへの画面遷移を行っている。

今回はTableViewCellを複数回選択した場合に、遷移先のVCが複数回呼ばれ重なって表示されてしまう。

原因としては、
Cell選択時のtableView:didSelectRowAtで負荷の大きいサーバー通信により、
後続処理である画面遷移までに遅延が発生し、その間に次のCell選択イベントが呼ばれてしまっている。

そのため、初回のCell選択イベントが終了する前に
複数のCell選択イベントが発生しているため、これを単一にする必要がある。

対策

その対策として、
初回のCell選択イベント発生時に、イベント終了までTableView全体のタッチイベントを無効にさせる。
isMultipleTouchEnabled または isUserInteractionEnabled
➡ 今回は、タッチイベントのみ対象とすればいいからisMultipleTouchEnabledを使用してみる。

初回または戻ってきた場合において、タッチイベントを有効にしておく。

override func viewWillAppear(_ animated: Bool) {
    tableView.isMultipleTouchEnabled = true
}


現在のCell選択イベント発生の有無により、タッチイベント操作を確定する。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    // Cell選択イベント発生の有無を確認する
    if !tableView.isMultipleTouchEnabled {return}

    // タッチイベントを無効にする
    tableView.isMultipleTouchEnabled = false
    
    // 負荷の大きいサーバー通信処理を仮定して、0.5秒後に実行させる
    DispatchQueue.main.asyncAfter(wallDeadline: .now() + 0.5) {
        let vc = NextViewController.init(nibName: "NextViewController", bundle: nil)
        self.navigationController?.pushViewController(vc, animated: true)
    } 
}

イベント発生有の場合 ➡ 処理を中断する。
イベント発生無の場合 ➡ 処理続行しタッチイベントを無効にする。処理終了時にタッチイベントを有効に戻す。

isUserInteractionEnabledの場合であったても同様。

isMultipleTouchEnabled

When set to true, the view receives all touches associated with a multi-touch sequence and starting within the view's bounds. When set to false, the view receives only the first touch event in a multi-touch sequence that start within the view's bounds. The default value of this property is false.


trueに設定すると、ビューはマルチタッチシーケンスに関連付けられていてビューの境界内から始まるすべてのタッチを受け取ります。 falseに設定すると、ビューは、ビューの境界内で始まるマルチタッチシーケンスの最初のタッチイベントのみを受け取ります。このプロパティのデフォルト値はfalseです。

isMultipleTouchEnabled - UIView | Apple Developer Documentation

isUserInteractionEnabled

When set to false, touch, press, keyboard, and focus events intended for the view are ignored and removed from the event queue. When set to true, events are delivered to the view normally. The default value of this property is true.


falseに設定すると、ビューを対象としたtouch、press、keyboard、およびfocusイベントは無視され、イベントキューから削除されます。 trueに設定すると、イベントは通常通りビューに配信されます。このプロパティのデフォルト値はtrueです。
isUserInteractionEnabled - UIView | Apple Developer Documentation

まとめ

実際に動きも確認できた。

参考

【Swift】CollectionViewで複数の画像を横スクロールさせたい

複数の画像を1行で横スクロールできるように並べたい。 https://cdn-ak.f.st-hatena.com/images/fotolife/C/CHU-BURA/20190706/20190706194915_original.png 調べるとCollectionViewで再現できるみたいで、
けっこう参考になる記事がたくさんあって思いのほか簡単に再現できた。

そこで触れてみた感触としてTableViewと似ているが、
個人的にTableViewとは少し違うなと感じたCollectionViewの部分を書いていく。

スクロール方向の指定

TableViewとは異なり、縦または横スクロールが可能。
指定しない場合は、デフォルトの縦スクロールとなる。

delegate側で設定できるものだと思っていたが、基本的にはcell登録時にUICollectionViewFlowLayoutに対して設定するみたい。

let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal // 横スクロール
collectionView.collectionViewLayout = layout

Cellサイズの設定

先ほど同様にcell登録時のUICollectionViewFlowLayoutに対して設定できる。

let layout = UICollectionViewFlowLayout()
let size = collectionView.frame.height
layout.itemSize = CGSize(width: size, height: size)
collectionView.collectionViewLayout = layout

または、TableView同様にdelegateであるUICollectionViewDelegateFlowLayoutでも設定できる。

extension ViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let size = collectionView.frame.height
        return CGSize(width: size, height: size)
    }
}

まとめ

簡単に縦、横画面のものを作ってみた。実際にはこんな感じ

20190706185626

参考

【Swift】UILabelで単位部分(◯秒・◯cm)の一部文字サイズを変更したい

UILabelとかで「10秒」や「10cm」といった、
ある単位を含む文字を表示させたい場合において、その単位部分のみ文字サイズを小さく表示させたいということがある。
→「〇〇」「〇〇cm」など

そのUILabelを一箇所でしか使用しない場合であれば、
以下のように直接Attributeで一部サイズを変更すれば問題なさそう。

しかし、
・複数箇所で使用する場合
・「10秒」「20秒」「30秒」といった値が可変する場合
・「10秒」「10cm」「10kg」といった単位が可変する場合
などでは上記の方法は現実的ではない....

そこでUILabelを拡張して、
上記の条件でも単位部分の文字サイズを変更できるようにしてみた。 ここでは、単位サイズを値の半サイズで表示させている。

Swift4

extension UILabel {
    func addUinit(unit: String, size: CGFloat) {
        guard let label = self.text else {
            return
        }
        // 単位との間隔
        let mainString = NSMutableAttributedString(string: label + " ")
        let unitString = NSMutableAttributedString(
            string: unit,
            attributes: [.font: UIFont.systemFont(ofSize: size)])
        let attributedString = NSMutableAttributedString()
        attributedString.append(mainString)
        attributedString.append(unitString)
        
        self.attributedText = attributedString
    }
}

// cm
label1.text = "10"
label1.addUinit(unit: "cm", size: label1.font.pointSize / 2)
print(label1.text!) // 10 cm

// 秒
label2.text = "60"
label2.addUinit(unit: "秒", size: label2.font.pointSize / 2)
print(label2.text!) // 60 秒

Swift3

Swift3では、 .font: UIFont.systemFont(ofSize: size)部分がNSAttributedString.Key.font : UIFont.systemFont(ofSize: size)になりそう。

参考

【Mac】キーボードのキー長押しによる連続入力ができない

MacBookMac純正キーボードだとあまり遭遇することはないと思うんだが...

非純正のキーボード使っていたりすると、普段いつものように使っている
Delete長押し』長押し』などができない場合がある。

最初の頃は我慢してたけど、さすがに...
と思い調べてたらApple公式でこんな質問を見つけて

Q: キー押しっぱなしの連続入力が出来ない
最近、キーボードでキーを押しっぱなしにした時に出来るはずの連続文字入力が出来なくなってしまいました。
例えばdeleteキーもそうで、ブラインドタッチが満足に出来ないので、キーボードを見ながら打った後に間違いに気付き、deleteキーをずっと押していてもカーソルが後退せず、文字分deleteキーを打たねばならないような事になっております。
古いキーボードを代わりに繋いでみても同じ状況なので、設定がおかしくなっているのではないかと思っていますが、いくら探しても見つかりません。 そんな設定はあるのでしょうか? 修復法はあるでしょうか?

うん、まさに直面している質問だった。

原因

どうやら、キーボードの設定にある
キーのリピート」または「リピート入力認識までの時間」が原因みたい。

今回のように連続入力できない場合は、このどちらかが設定されている。

  • [キーボード] > [キーのリピート] が、 または オフ になっている。
  • [キーボード] > [リピート入力認識までの時間] が 、長い になっている。

f:id:CHU-BURA:20190526150407p:plain

設定変更手順

  1. システム環境設定を開く。
  2. [キーボード] パネルを選択する。※OSによっては [キーボードとマウス]
  3. キーボードタグにある [キーのリピート] または [リピート入力認識までの時間] を変更する。
  4. [キーのリピート] を切(オフ)以外に、[リピート入力認識までの時間] を長い以外に設定する。

f:id:CHU-BURA:20190526150747p:plain

キーのリピート / リピート入力認識までの時間

  • キーのリピート
    同じキーを一定時間押し続けられる反応速度の設定ができる。

  • リピート入力認識までの時間
    同じキーを入力した場合の認識時間の設定ができる。

参考