20210120のSwiftに関する記事は8件です。

[Swift] UIButtonクラスをコードで作る

UIButtonクラスを作る

ボタンはUIButtonクラスなので、インスタンスでボタンを作れます。

準備

ボタンのバックグラウンドの画像を適当にダウンロードします。
ダウンロード.png

上の画像をAssetsフォルダの中に入れます。
これで準備完了です。

やってみる

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        //ボタンを作る
        let okButton=UIButton()
        //領域とボタンの位置
        okButton.frame=CGRect(x:100,y:100,width: 120,height: 120)
        //背景画像
        let bkgImage=UIImage(named: "maru.png")
        okButton.setBackgroundImage(bkgImage, for: .normal)

        view.addSubview(okButton)
    }
}

まず、UIButtonのインスタンスをokButtonに格納します。
そして、ボタンの位置とサイズをCGRect型で決定します。
背景画像をUIImage型で読み込んで,setBackgroundImageメソッドの引数に値を渡します。

最後に、view.addSubViewメソッドの引数にokButtonを渡します。
これは、viewにボタンを表示するためのメソッドです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

SwiftyTesseractとOpenCVを入れたら「duplicate symbol」しまくった話

タイトルの通り。duplicate symbolが出まくって面を食らったので解決策を備忘録として残しておきます。

環境情報

名前 バージョン
Xcode 12.3 (12C33)
Swift 5.3.2 (swiftlang-1200.0.45 clang-1200.0.32.28)
SwiftyTesseract 4.0.0
CMake 3.19.3
Python 2.7.16
xcode-select 2384
OpenCV 4.5.1

SwiftyTesseractとOpenCVを同じプロジェクトで使う

二つを同じプロジェクトで使うための手順を示します。

SwiftyTesseractをプロジェクトに追加する

2021年1月19日現在、SwiftyTesseractはSwift Package Managerからしか追加できませんので、Swift Package Managerから追加します。

Xcode上で「File > Swift Packages > Add Package Dependency...」と選択して、1.png
入力欄に以下のGitHubのURLを入力します。

https://github.com/SwiftyTesseract/SwiftyTesseract

2.png

OpenCVをプロジェクトに追加する

iOS用にビルドする

GitHubからOpenCVを入手して、platform/ios/にある以下のコマンドでiOS用にビルドします。

$ ./platform/ios/build_framework.py <output_dir>

ビルドしたframeworkファイルをプロジェクトに追加する

プロジェクトファイルを選んで、左ペインの「TARGETS」からアプリを選択します。
そして「Build Phases > Link Binary With Libraries (n items)」と選択して、ビルドで出力された「opencv2.framework」をドラッグ&ドロップなどで追加します。
3.png

Other Linker Flagsに-all_loadを追加する

プロジェクトファイルを選んで、左ペインの「PROJECT」からアプリを選択します。
「Build Settings」を選択して、「Linking > Other Linker Flags」に-all_loadを追加します。
6.png

libc++.tbdをプロジェクトに追加する

同じくプロジェクトファイルの「TARGETS」からアプリを選択します。
そして「General > Frameworks, Libraries, and Embedded Content」と選択して、左下の「+」ボタンを押します。
4.png
検索窓に「libc++」と入力すると「libc++.tbd」が出てくると思うのでそれを追加します。
5.png

試しにビルドしてみるが…

試しにビルドしてもこの時点ではうまくいきません。エラーを見ると「509 duplicate symbols for architecture x86_64(シミュレータなら×86_64、実機ならarm64)」というものすごい数の競合が起きていることがわかります。
7.png
解決方法ですが、opencv2.frameworkから競合が起きているファイルを削除することで解消できます。

競合が起きているファイル(.oファイル)をまとめる

エラーを頼りに競合が起きてるファイルをまとめます。執筆者の環境では以下のファイル内で競合が起きていました。

jutils.o pngrio.o pngwio.o jdcoefct.o jaricom.o jdmainct.o jdcolor.o pngerror.o jfdctint.o pngget.o pngrutil.o jmemmgr.o jccoefct.o jcmaster.o jidctflt.o pngpread.o jcprepct.o jerror.o pngset.o jctrans.o jcparam.o jdinput.o pngwtran.o jdarith.o jdsample.o jcomapi.o png.o pngrtran.o jchuff.o jddctmgr.o jidctfst.o jfdctfst.o pngwrite.o jfdctflt.o jdatasrc.o jdapistd.o pngmem.o jdapimin.o pngwutil.o jcdctmgr.o jdtrans.o jdhuff.o jdmaster.o jcapistd.o jdatadst.o jquant2.o jdmerge.o jmemnobs.o jccolor.o jdmarker.o jdpostct.o jcmarker.o jidctred.o jcarith.o jcmainct.o pngtrans.o jcinit.o jcsample.o jquant1.o pngread.o jidctint.o jcapimin.o

上記リストは、後でコマンドに引数として食わせるときに使いやすいようテキストファイルなどに書いておきます。

$ echo "jutils.o pngrio.o ..." > duplicate_lib_list

OpenCVをアーキテクチャごとに分解する

lipoコマンドを使って、フレームワークフォルダ内のopencv2をアーキテクチャごとに分解します。

まず何が含まれているか以下コマンドで確認して、

$ cd opencv2.framework
$ lipo -info opencv2
Architectures in the fat file: opencv2 are: armv7 armv7s i386 x86_64 arm64

以下コマンドでバラします。

$ lipo -thin armv7 opencv2 -output opencv2_armv7
$ lipo -thin armv7s opencv2 -output opencv2_armv7s
$ lipo -thin i386 opencv2 -output opencv2_i386
$ lipo -thin x86_64 opencv2 -output opencv2_x86_64
$ lipo -thin arm64 opencv2 -output opencv2_arm64

競合が起きているファイルを削除する

バラしたファイルに対して以下コマンドを実行して、競合が起きているファイルをそれぞれから削除します。

$ cat duplicate_lib_list | xargs ar -dv opencv2_armv7
$ cat duplicate_lib_list | xargs ar -dv opencv2_armv7s
$ cat duplicate_lib_list | xargs ar -dv opencv2_i386
$ cat duplicate_lib_list | xargs ar -dv opencv2_x86_64
$ cat duplicate_lib_list | xargs ar -dv opencv2_arm64

バラしたファイルから再生成する

以下コマンドを実行してopencv2を再生成しましょう。

$ lipo -create opencv2_arm64 opencv2_armv7 opencv2_armv7s opencv2_i386 opencv2_x86_64 -output opencv2

あとは途中作ったテキストファイルなどの余計なファイルを削除してリビルドしましょう。
競合が解消されてビルドできるようになっているはずです!

参考記事

  1. OpenCV が Objective-C / Swift で使えるようになります & 使ってみた - Qiita
  2. Xcodeでビルドした時の”duplicate symbols”エラーを回避する
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

今更だけどUIViewの座標変換系メソッドを理解する(Swift)

Xcode-12 iOS-14.0 Swift-5.3

はじめに

ごくまれに UIView の convert 系のメソッドを使って座標を変換したいときがありますがいつもどっちに何指定するのかな?と忘れるのでまとめておきます。

View 準備

下記のような構成で座標変換をしてみます。

xib

views

ScrollView を ViewController の View と同じサイズで配置してその中に contentView (緑色)を幅は ScrollView と同じ高さは 1200 pt で配置しています(StackView は左端のメモリ用です)。contentView の中に縦横 120 pt の targetView (白色)を contentView の Top 900pt、横は中央寄せで配置して、その targetView (白色)の中心にボタンを配置しています。

座標変換

座標変換には UIView に下記のメソッドが用意されており、これを使って変換します。

どちらのメソッドも対象の View は同一 Window にある必要があります。引数の viewnil の場合は Window の座標系に変換されます。

convert(_: to:)

point はレシーバーの座標系を指定し、view には変換したい座標系の View を指定します。

func convert(_ point: CGPoint, to view: UIView?) -> CGPoint

// ex.
aView.convert(CGPoint.zero, to: bView)

例だと aView の左上の座標を bView の座標系に変換しています。

convert(_: from:)

pointview の座標系を指定し、レシーバーの座標系に変換します。

func convert(_ point: CGPoint, from view: UIView?) -> CGPoint

// ex.
aView.convert(CGPoint.zero, from: bView)

例だと bView の左上の座標を aView の座標系に変換しています。

実践

ボタン押下時に targetView の座標系から scrollView と ViewController の view の座標系に変換してみます!

 @IBAction private func convertPoints(_ sender: Any) {
    // targetViewの右上の座標をscrollViewの座標系に変換
    let p1 = targetView.convert(CGPoint.zero, to: scrollView)
    print("p1: \(p1)") // p1: (127.5, 900.0)

    // targetViewの右上の座標をviewの座標系に変換
    let p2 = targetView.convert(CGPoint.zero, to: view)
    print("p2: \(p2)") // p2: (127.5, 367.0) * scrollViewのoffsetで変わる

    // targetViewの右上の座標をscrollViewの座標系に変換 
    let p3 = scrollView.convert(CGPoint.zero, from: targetView)
    print("p3: \(p3)") // p3: (127.5, 900.0)

    // targetViewの右上の座標をviewの座標系に変換 
    let p4 = view.convert(CGPoint.zero, from: targetView)
    print("p4: \(p4)") // p4: (127.5, 367.0) * scrollViewのoffsetで変わる
}

上記を見てもらうと分かる通り、p1 と p3、p2 と p4 は同じ結果になります。

これを使ってボタン押下時に targetView が画面外にある場合にスクロールのオフセットを調節してみます。

@IBAction private func convertPoints(_ sender: Any) {
    // targetViewの左下の座標をviewの座標系に変換
    let p1 = targetView.convert(CGPoint(x: 0, y: targetView.frame.height), to: view)
    // targetViewの左下がviewの範囲内か確認
    if !view.frame.contains(p1) {
        // targetViewが画面内におさまるようスクロール
        let p2 = targetView.convert(CGPoint(x: 0, y: targetView.frame.height), to: scrollView)
        scrollView.setContentOffset(.init(x: 0, y: p2.y - scrollView.frame.height), animated: true)
    }
}

こんな感じです:tada:

scroll

おわりに

to と from の意味を考えたらわかるんですが point はどの座標系のやついれればいいんだっけ?とよく迷います。。。

もうこれで迷わない!!(たぶん:rolling_eyes:

ちなみに Rect の変換メソッドもあります。
* convert(_: to:)
* convert(_: from:)

SwiftUI になるとこういうの使うこともなくなるのかな:thinking:

参考

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Swift 繰り返し文まとめ

はじめに

この記事には、Swiftで多用する繰り返し文についてまとめました。

参考文献

この記事は以下の情報を参考にして執筆しました。

目次

  1. for-in文 - シーケンスの要素の列挙
  2. while文 - 継続条件による繰り返し
  3. repeat-while文 - 初回実行を保証する繰り返し
  4. 実行文の中断

1. for-in文 - シーケンスの要素の列挙

Sequenceプロトコルに準拠した型(ArrayやDittionary等)の要素にアクセスするための制御構文。
各要素を実行文に順次渡しながらその要素の数だけ繰り返す。
実行文内では、要素名として指定した名前の定数を通じて要素にアクセスできる。

for 要素名 in シーケンス {
要素ごとに繰り返し実行される文
}

Array型の要素をfor-in文で列挙する場合、要素の型はElement型となる。
Dictionary型の要素をfor-in文で列挙する場合、要素の型は(Key, Value)型のタプルとなる。

2. while文 - 継続条件による繰り返し

条件式が成り立つ限り繰り返しを続ける制御構文。
while文は条件式と繰り返し実行される文から構成されている。
while文の条件式は、if文やfor-in文と同様にBool型を返す必要がある。
条件式は実行文の実行前に毎回評価され、結果がtrueであれば繰り返しを継続し、falseであれば繰り返しを停止し、while文全体の処理を終了する。

while 条件式 {
条件式が成立する間、繰り返し実行される文
}

3. repeat-while文 - 初回実行を保証する繰り返し

通常while文は実行前に評価を行うので、場合によっては一度も処理が行われない場合がある。だが、repeat-while文を使えば条件式は実行文の後に評価されるので条件の成否に関わらず、必ず一回は処理が行われる。

repeat {
一回は必ず処理され、それ以降は条件式が成立する限り繰り返し実行される文
} while 条件式

4. 実行文の中断

break文 - 繰り返しの終了

実行文を中断し、繰り返し文全体を終了する。
これ以上繰り返しを行う必要がない場合などに使用する。

continue文 - 繰り返しの継続

実行文を中断した後、後続の繰り返しを継続する。
特定の場面だけ処理をスキップしたい場合など使用する。
continue文は、continueキーワードのみかラベルとの組み合わせで使用する。

ラベル - break文やcontinue文の制御対象の指定

break文やcontinue文はラベルを用いて制御対象を指定できる。
ネストした繰り返しから一度退出する場合などに使用する。
ラベルによって繰り返し文を参照可能にするには、繰り返し文の前にラベル名:を追加する。

ラベル名: 繰り返し文

breakやcontinueキーワードに続けてラベル名を追加することで対象の繰り返し文を明示する。

break ラベル名

continue ラベル名

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swift】スワイプ処理を実装する

はじめに

アプリ開発していく中で、スワイプジェスチャーを使用しました。そこで今回はスワイプジェスチャーについてまとめます。

開発環境

  • macOS Catalina version10.15.7
  • Xcode version12.2
  • Swift5

様々なジェスチャー

Appleのヒューマンインターフェースガイドラインより、様々なジェスチャーの動画を確認できます。
Human Interface Guidelines

ガイドラインを見ていて、フリックとスワイプって何が違うのか?と思ったので調べてみました。

フリックとスワイプの違いは?

フリック:画面を指で軽くはじくイメージ。文字入力などに使う。
スワイプ:画面に指を触れたままスライドさせるイメージ。画面遷移などに使う。

参考サイト:「スワイプ」と「フリック」の違い・活用術 今さら聞けないスマホの基本操作

確かにフリック入力って言いますね。(自分は文字入力はタップ入力に慣れてしまっているためイメージしにくかったのかも)

スワイプ処理実装

全体のコード

import UIKit

//UIGestureRecognizerDelegateを追加する
class ViewController: UIViewController, UIGestureRecognizerDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()

        //上スワイプ用のインスタンスを生成する
        let upSwipe = UISwipeGestureRecognizer(
            target: self,
            action: #selector(ViewController.didSwipe(_:))
        )
        upSwipe.direction = .up
        self.view.addGestureRecognizer(upSwipe)

        //右スワイプ用のインスタンスを生成する
        let rightSwipe = UISwipeGestureRecognizer(
            target: self,
            action: #selector(ViewController.didSwipe(_:))
        )
        rightSwipe.direction = .right
        self.view.addGestureRecognizer(rightSwipe)

        //下スワイプ用のインスタンスを生成する
        let downSwipe = UISwipeGestureRecognizer(
            target: self,
            action: #selector(ViewController.didSwipe(_:))
        )
        downSwipe.direction = .down
        self.view.addGestureRecognizer(downSwipe)

        //左スワイプ用のインスタンスを生成する
        let leftSwipe = UISwipeGestureRecognizer(
            target: self,
            action: #selector(ViewController.didSwipe(_:))
        )
        leftSwipe.direction = .left
        self.view.addGestureRecognizer(leftSwipe)

    }

    //スワイプ時に実行されるメソッド
    @objc func didSwipe(_ sender: UISwipeGestureRecognizer) {

        //スワイプ方向による実行処理をcase文で指定
        switch sender.direction {
        case .up:
            //上スワイプ時に実行したい処理
        case .right:
            //右スワイプ時に実行したい処理
        case .down:
            //下スワイプ時に実行したい処理
        case .left:
            //左スワイプ時に実行したい処理
        default:
            break
        }
    }
}

参考:【Swift/UIKit】タップ・長押し・スワイプを認識させる

解説

スワイプ処理は、方向の指定箇所以外は同じ処理のためここでは上スワイプ処理のコードを使って簡単に説明します。

//上スワイプ用のインスタンスを生成する
let upSwipe = UISwipeGestureRecognizer(
    target: self,
    action: #selector(ViewController.didSwipe(_:))
)
upSwipe.direction = .up
self.view.addGestureRecognizer(upSwipe)

タップ、ロングプレスと同様に、まずはインスタンスを生成する。
その際に、スワイプジェスチャー時に実行したいメソッドを指定する。
メソッド指定時に#selectorを使用している理由や、メソッド定義時に@objcは下記の通りです。

target-actionはObjective-Cで実装された仕組みで、target-actionで指定するのはObjective-Cのメソッドである必要がある。そのため、メソッド定義時は@objcをつけている。
また、Swiftでは#selectorによってObjective-Cのメソッドを指定できるとのこと。
参考:【Swift】タップ、ロングプレス処理を実装する!


upSwipe.direction = .up

directionよりスワイプの方向を指定する。
スワイプの方向は全部で4つ。right,left,up,down
公式ドキュメント UISwipe Gesture Recognizer .Direction


self.view.addGestureRecognizer(upSwipe)

addGestureRecognizer()でスワイプイベントをviewに追加しています。


//スワイプ時に実行されるメソッド
@objc func didSwipe(_ sender: UISwipeGestureRecognizer) {

    //スワイプ方向による実行処理をcase文で指定
    switch sender.direction {
    case .up:
        //上スワイプ時に実行したい処理
    case .right:
        //右スワイプ時に実行したい処理
    case .down:
        //下スワイプ時に実行したい処理
    case .left:
        //左スワイプ時に実行したい処理
    default:
        break
    }
}

各スワイプ時に実行する処理がこちらになります。
Switch文を用いて、スワイプの方向によって実行する処理を設定しています。

【おまけ】ジェスチャーを無効、有効化するには?

最初ジェスチャーの無効、有効化を調べていたところ下記コードでできるという記事を見つけました。

UIApplication.shared.beginIgnoringInteractionEvents() //無効化
UIApplication.shared.endIgnoringInteractionEvents() //有効化

しかし、実装してみたところ下記警告が出ました。

beginIgnoringInteractionEvents()' was deprecated in iOS 13.0: Use UIView's userInteractionEnabled property instead

どうやら、iOS13より上記コードは非推奨になったらしいです。userInteractionEnabledを使ってくださいとのことでした。

userInteractionEnabledを用いた無効、有効化はこちらになります。

self.view.isUserInteractionEnabled = false //ジェスチャー無効
self.view.isUserInteractionEnabled = true //ジェスチャー有効(デフォルト値)

参考:公式ドキュメント isUserInteractionEnabled

まとめ

今回はスワイプ処理に関する学んだことをまとめました。
普段何気なく使っているスワイプ処理がこんな感じで実装されているんだなぁと知ることができて勉強になりました。

以上。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swift5】iOSの設定アプリに遷移するための処理と注意点

iOSの設定アプリに遷移させるための処理

guard let url = URL(string: UIApplication.openSettingsURLString), UIApplication.shared.canOpenURL(url) else { return }
UIApplication.shared.open(url, options: [:], completionHandler: nil)

注意点

①設定アプリに遷移するときの挙動

「設定アプリ」内にアプリ固有の設定項目がある場合は、アプリ固有の設定画面へ遷移します。

詳細な挙動については、下記の記事が参考になります。
UIApplicationOpenSettingsURLStringから設定アプリを開いたときの挙動調査

②設定アプリの特定の画面に遷移させる処理(App-Prefs:root=)を使うとリジェクトされる

設定アプリの特定の画面に遷移させるとリジェクトされた例があるらしいので注意が必要です。

詳しくは下記記事に書かれています。
App-Prefs:root= を使っていたため2.5.1リジェクトされたときの対処法

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

gem install cocoapods に 失敗('ruby/config.h' file not found)

少しハマったので備忘録として残しておきます。

環境

MacOS : Big Sur 11.1 (20C69)
Xcode : Version 12.3 (12C33)

経緯

pod コマンドを使用したところ、cocoapodsをアップデートしてねと言われる

% pod outdated
Ignoring ffi-1.13.1 because its extensions are not built. Try: gem pristine ffi --version 1.13.1
Ignoring iStats-1.6.1 because its extensions are not built. Try: gem pristine iStats --version 1.6.1
Updating spec repo `trunk`

CocoaPods 1.10.1 is available.
To update use: `sudo gem install cocoapods`
 :

エラー内容

ほいほいとアップデート実行すると以下のエラーが発生

% sudo gem install cocoapods
Password:
Ignoring ffi-1.13.1 because its extensions are not built. Try: gem pristine ffi --version 1.13.1
Ignoring iStats-1.6.1 because its extensions are not built. Try: gem pristine iStats --version 1.6.1
ERROR:  Error installing cocoapods:
    ERROR: Failed to build gem native extension.

    current directory: /Library/Ruby/Gems/2.6.0/gems/ffi-1.13.1/ext/ffi_c
/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/bin/ruby -I /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0 -r ./siteconf20210120-82832-1x09kaf.rb extconf.rb
checking for ffi.h... /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:467:in `try_do': The compiler failed to generate an executable file. (RuntimeError)
You have to install development tools first.
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:585:in `block in try_compile'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:534:in `with_werror'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:585:in `try_compile'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:1109:in `block in have_header'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:959:in `block in checking_for'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:361:in `block (2 levels) in postpone'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:331:in `open'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:361:in `block in postpone'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:331:in `open'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:357:in `postpone'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:958:in `checking_for'
    from /System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib/ruby/2.6.0/mkmf.rb:1108:in `have_header'
    from extconf.rb:10:in `system_libffi_usable?'
    from extconf.rb:42:in `<main>'

To see why this extension failed to compile, please check the mkmf.log which can be found here:

  /Library/Ruby/Gems/2.6.0/extensions/universal-darwin-20/2.6.0/ffi-1.13.1/mkmf.log

extconf failed, exit code 1

Gem files will remain installed in /Library/Ruby/Gems/2.6.0/gems/ffi-1.13.1 for inspection.
Results logged to /Library/Ruby/Gems/2.6.0/extensions/universal-darwin-20/2.6.0/ffi-1.13.1/gem_make.out

/Library/Ruby/Gems/2.6.0/extensions/universal-darwin-20/2.6.0/ffi-1.13.1/mkmf.log
上記のエラーログを見てねと言われる。

/Library/Ruby/Gems/2.6.0/extensions/universal-darwin-20/2.6.0/ffi-1.13.1/mkmf.log
package configuration for libffi is not found
"xcrun clang -o conftest -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/include/ruby-2.6.0/universal-darwin20 -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/include/ruby-2.6.0/ruby/backward -I/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/include/ruby-2.6.0 -I. -D_XOPEN_SOURCE -D_DARWIN_C_SOURCE -D_DARWIN_UNLIMITED_SELECT -D_REENTRANT    -g -Os -pipe -DHAVE_GCC_ATOMIC_BUILTINS -DUSE_FFI_CLOSURE_ALLOC conftest.c  -L. -L/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/lib -L. -L/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX11.1.Internal.sdk/usr/local/lib     -lruby.2.6   "
In file included from conftest.c:1:
In file included from /Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/include/ruby-2.6.0/ruby.h:33:
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/include/ruby-2.6.0/ruby/ruby.h:24:10: fatal error: 'ruby/config.h' file not found
#include "ruby/config.h"
         ^~~~~~~~~~~~~~~
/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks/Ruby.framework/Versions/2.6/usr/include/ruby-2.6.0/ruby/ruby.h:24:10: note: did not find header 'config.h' in framework 'ruby' (loaded from '/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/System/Library/Frameworks')
1 error generated.
checked program was:
/* begin */
1: #include "ruby.h"
2:
3: int main(int argc, char **argv)
4: {
5:   return 0;
6: }
/* end */

対処方法

Xcode の設定(Preferences)から「Locations」タブを開く
「Command Line Tools」が空だったので 「Xcode 12.3(12C33)」を選択

スクリーンショット 2021-01-20 13.12.30.png

上記の設定を行い、再度 sudo gem install cocoapodsを実行したところ無事インストール完了しました。

参考

https://stackoverflow.com/questions/26434642/yosemite-upgrade-broke-ruby-h

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【Swift】SafeAreaの高さを取得する

SafeAreaの高さを取得したかったので調べました。

SafeAreaの高さ

//上部のSafeArea
let safeAreaTop = self.view.safeAreaInsets.top
print(safeAreaTop)

//下部のSafeArea
let safeAreaBottom = self.view.safeAreaInsets.bottom
print(safeAreaBottom)

ちなみに

viewDidLoadの時点ではSafeAreaの値は取得出来なかったのでviewWillLayoutSubviewsの時に取得するのが良さそうです。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む