20200305のiOSに関する記事は6件です。

iOS13.3.1の環境で実機テストするとLibrary not loaded が表示される件について

こんにちは。
先日、外部フレームワークを使ったアプリで実機テストしようとしたら、真っ黒な画面になってしまい、少々ハマってしまったので記事を書きます。
同じことが起きてる人がいたら参考にして欲しいです。

環境

Xcode11.3.1
iOS(実機)13.3.1

解決すべき問題

Firebaseなどの外部ライブラリをCocoaPodsで導入したアプリを実機にインストールすると、「Library not loaded」となって、画面が真っ黒くなるという問題。なお、シュミレーターでは普通に動く。

原因

iOS13.3.1から、Appleは無料のアカウントで外部フレームワークを使用することをブロックしたらしいです、、、
僕は試してないんですが、有料版にアップグレードすると動くらしいです。

解決するためにやったこと

とりあえずエラーをコピペして検索してみた。そしたら、上の原因に書いたことが影響しているってことは分かったのですが、じゃあ1万円払って有料のデベロッパーアカウントを作成するのもなんか悔しい。

それで色々調べた結果、無料アカウントでも外部フレームワーク使える方法がありました。
それは、Podfileのuse_frameworks!をuse_modular_headers!に変更するという方法です。

こんな感じに、、、

# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'AppName' do
  # Comment the next line if you don't want to use dynamic frameworks
  # use_frameworks!
  use_modular_headers!

  # Pods for AppName

  pod 'Firebase'
  pod 'Firebase/Analytics'

end

ここでは、use_frameworks!をコメントアウトしています。

もし、せっかく作ったアプリが動かなくて困っている方がいたら参考にしていただければと思います。

参考にしたサイト

https://stackoverflow.com/questions/60096258/library-not-loaded-rpath-fblpromises-framework-fblpromises-ios-13-3-1

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

【iOS】FirebaseのFriendly-Chatチュートリアルの pod install でエラーが出るとき

FirebaseのCodelabでのチュートリアル Friendly Chat で pod install でエラーが出るのは、Podfileが古いからのようだった。
https://codelabs.developers.google.com/codelabs/firebase-ios-swift/?hl=ja#2

Pod::StandardError - [Bug] Failed to find known source with the URL "trunk"

[!] Oh no, an error occurred.

一度、Podfile, Podfile.lockを削除して、そのディレクトリでpod initし、そこに元の情報を正しくコピペしてやると成功した。

スクリーンショット 2020-03-05 17.03.14.png

podfile
# Uncomment the next line to define a global platform for your project
# platform :ios, '9.0'

target 'FriendlyChatSwift' do
  # Comment the next line if you're not using Swift and don't want to use dynamic frameworks
  use_frameworks!

  # Pods for FriendlyChatSwift
  # FriendlyChat Codelab

pod 'Firebase/AdMob'
pod 'Firebase/Analytics'
pod 'Firebase/Auth'
pod 'Firebase/Database'
pod 'Firebase/RemoteConfig'
pod 'Firebase/Storage'
pod 'Firebase/Crashlytics'
pod 'GoogleSignIn'


end

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

歴代iPhoneの販売開始年/初期搭載iOS ver./最終iOS ver

iOSアプリの最小iOSバージョンを検討するために一覧化しています。

iPhone 販売開始年 初期搭載 iOS ver. 最終 iOS ver.
iPhone 11 Pro/11 Pro Max 2019 13 未発表
iPhone 11 2019 13 未発表
iPhone XR 2018 12 未発表
iPhone XS/XS Max 2018 12 未発表
iPhone X 2017 11.1 未発表
iPhone 8 / 8 Plus 2017 11 未発表
iPhone 7 / 7 Plus 2016 10 未発表
iPhone SE 2016 9.3 未発表
iPhone 6s / 6s Plus 2015 9 未発表
iPhone 6 / 6 Plus 2014 8 12.4
iPhone 5s 2013 7 12.4
iPhone 5c 2013 7 10.3
iPhone 5 2012 6 10.3
iPhone 4S 2011 5 9.3
iPhone 4 2010 4 7.1
iPhone 3GS 2009 3 6.1
iPhone 3G 2008 2 4.2

※ 2020年3月時点のものです

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

スマホ向けセカンドスクリーンという新セグメント

RoshScreen.png

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

【Swift】Navigation Controllerをコードで実装する

Storyboardでいうところの、以下のようなNavigation Controllerをコードで実装する方法をご紹介します

スクリーンショット 2020-03-05 10.09.57.png

まず、UINavigationControllerを継承したクラスを作成します

NavigationController.swift
class NavigationController: UINavigationController {

    override func viewDidLoad() {
        super.viewDidLoad()

    }
}

AppDelegateに以下のように記述します

AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {

    var window: UIWindow?

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

        let nav = NavigationController()
        let vc = ViewController()
        nav.viewControllers = [vc]

        //NavigationControllerをrootViewに設定する
        window?.rootViewController = nav
        window?.makeKeyAndVisible()

        return true
    }
}

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

SwiftUIのViewは自分のサイズを自分で決めます

もと(英語)→
https://netsplit.com/swiftui/views-choose-their-own-sizes/

外国人なので日本語がおかしいところがあれば是非教えてください。

SwiftUIの紹介記事などでだいたい最初に書かれるのは「ビューは自分で自分のサイズを決め、一回決められたサイズは上書きできません」とのことですが、こんな簡単そうなことでも以外と複雑な闇を隠しています。なぜならその簡単そうな宣言が我らの知っているレイアウトについての全ての常識を変えるのです。

SwiftUIはUIKitやAppKitの考え方とは違いますしメリットとデメリットもありますので時間をかけてちゃんと勉強する価値はあると思います。なのでこの記事ではたくさんのレイアウトの土台になるビューの2つ(ImageとText)を見ながら宣言の深い意味を考えてみましょう。

Images

まず画像を表示しましょう:

struct ContentView : View {
    var body: some View {
        Image("barbarian")
    }
}

ソース画像のサイズ(解像度)は 101px x 92px なので表示される画像も同じサイズになって、画面の真ん中に表示されます。

frame.png

見やすいため記事のスクショは全部ボーダー付きにしました。
画像のボーダーは全部「赤色」
デバイスのボーダーは「グレー」
フレームのボーダーは「緑色」
テキストのボーダーは「黄色」
他の記事でSwiftUIのボーダーについて書きますがとりあえず今回はビューのバウンドを見やすくするために使用し、コードからは抜きます。

.framemodifierを使うと画像をフレームの中に入れることができます。

struct ContentView : View {
    var body: some View {
        Image("barbarian")
            .frame(width: 200, height: 200)
    }
}

frame2.png

UIKit, AppKitなどだとこれは意外な結果ですよね?

画像を拡大するのじゃなくて、画像は同じサイズそのままフレームの真ん中にドンと置いてあるだけです。

結局のところ、.frameは使用されたビューのプロパティーを変更せず指定されたサイズで新しく "frame" というビューを作成し使用されたビューがその新しいフレームのチャイルドとして追加されます。

ポイント!!.frameは使用されたビューのプロパティーを変更せず指定されたサイズで新しく "frame" というビューを作成し使用されたビューがその新しいフレームのチャイルドとして追加されます。

これがSwiftUIの基礎的なところなのでちゃんと理解をした方がいいんじゃないかなと思います。 .frameみたいなmodifierは新しくビューを作成し元のビューが新しいビューにチャイルドとして追加されます。

Imageのサイズが画像アセットだけを元に選ばれます。親ビューがそれを上書きできません。

シンプルなデモとして小さすぎるフレームに画像をぶち込んでみましょう。

struct ContentView : View {
    var body: some View {
        Image("barbarian")
            .frame(width: 50, height: 200)
    }
}

多分これだと画像が必ずリサイズされる!かと思うのは普通ですが、SwiftUIだと画像がフレームをオーバーフローするだけです。

overflow.png

重ねられるビューを作る時、これは使えますね。
ですが、.clipped.cornerRadiusみたいな、画像を切り取るmodifierを使うとフレームのバウンドを元に画像を切り取ることは可能です。が、長くなるのでこの記事では詳しくは書かないことにします。

あとでまた画像に戻りますがここで他に確認するべきところがありますので一旦Textをみてみましょう。

Text

さっきのレイアウトを画像じゃなくてキャラクターの名前の文字列にしてみましょう。

struct ContentView : View {
    var body: some View {
        Text("Nogitsune Takeshi")
    }
}

text_frame.png

画像と同じように画面の真ん中に文章が表示されています。Textも文字がちゃんと入るサイズを自分で決めました。そして.frameも同じように使うことはできます。

struct ContentView : View {
    var body: some View {
        Text("Nogitsune Takeshi")
            .frame(width: 200, height: 200)
    }
}

.frameがもう1つの新しいビューを作ることを知っているとTextが前と同じく真ん中に置いてあることに驚きはないと思います。

text_frame_2.png

Textはサイズ選びに設定は色々ありますよ。例えば.fontでフォントを選べます。ヒーローの名前なので.titleにしましょう。

struct ContentView : View {
    var body: some View {
        Text("Nogitsune Takeshi")
            .font(.title)
    }
}

フォントが大きくなったので前よりテキストが大きくなっています。

title_text.png

画像の対応と完全に同じにするため大きくなったTextを小さすぎるフレームにぶち込んでみます。

struct ContentView : View {
    var body: some View {
        Text("Nogitsune Takeshi")
            .font(.title)
            .frame(width: 200, height: 200)
    }
}

似たコードで画像のサイズを全く変更せずにフレームをオーバーフローしてしまったが、Textだと.fontでサイズの変更できましたしこれの結果は違うのかな?!

title_text_multiline.png

オーバーフローせず、ちゃんとフィットするサイズを選ぶことはできたらしい。この場合だとコンテンツを2行に分け、横幅の広さを抑えて縦幅を大きくしました。

これは「親ビューは決まったサイズを上書きできない」とのことを矛盾しない。ただまだ勉強していないもう1つの原則を表す→ ビューが自分のサイズを決める前に親から「提案」をもらいます。

ポイント!!ビューが自分のサイズを決める前に親から「提案」をもらいます。

ちなみに「親が子に渡す提案サイズ」と「親が決める自分(親)のサイズ」は別物です。大体、親は子ビューを元に自分のサイズを選びますので。

Flexible Framesは複雑なので、他の記事でもう少し詳しく書きます。

提案サイズについて

前の例で、サイズを決めてビューが設置された手順の理解がSwiftUIの理解の鍵になります。Textが自分のサイズを決めて、そのサイズを上書き不可能。だがTextは親から渡されたサイズをもとに自分のサイズを柔軟に選べます。

Frameを200 x 200のサイズを指定したのでTextを設置する準備が終えた後にTextに提案サイズとして自分のサイズを渡し、その後フレームが、チャイルドになっているTextに自分のサイズを決めろと頼みます。

Frameがない例でデバイスのバウンドがTextに提案サイズを渡しました。

Frameがある例で提案された横幅(width)が足りなかったが縦幅(height)に十分のスペースがあったのでコンテンツを2行に分けたら収まることができます。

Textは親が渡した提案サイズを元に自分のコンテンツの最適な表示方法を決めてそのように表示してるのです!

普段は決められたサイズが提案サイズより小さいのがいいです、コンテンツが丁度入るぐらいの大きさ。んで、親から渡された提案サイズが大ぎるとしても自分がそのサイズに合わせて大きくなること基本的にないです。

それに、上の例のように提案サイズのwidthをそのまま選ぶじゃなくて、2行になった文字列が入るの、提案より小さいサイズになりました。Frameよりは小さいのでTextをFrameの真ん中に設置されることになりました。

ImageがFrameより大きい場合のようにTextがFrameより縦が大きい時も同じようなことが起きます。

struct ContentView : View {
    var body: some View {
        Text("Nogitsune Takeshi")
            .frame(width: 200, height: 10)
    }
}

ImageがFrameをオーバーフローするしTextもオーバーフローしちゃいます。

text_frame_overflow.png

テキストの切り捨て

サイズを柔軟に選ぶのに数行に分けるのはTextのたった1つの選択ではありません。文字と文字の間のスペースを小さくすることもでき、コンテンツを切り捨てることもできます。こうやって切り捨て機能を確認できます →

struct ContentView : View {
    var body: some View {
        Text("Nogitsune Takeshi")
            .font(.title)
            .lineLimit(1)
            .frame(width: 200, height: 200)
    }
}

.lineLimitを使ったことによって前の無限行数ではなく1行に収まるように命令しましたので、提案サイズが足りないときはTextが違うやり方でコンテンツを抑えてサイズを選ばないといけない。1行で文字列の横幅をフィットすることができず、数行使うこともできないのでTextが文字列を切り捨てて自分の横幅を減らすようにしてます。

title_text_frame.png

もう一度、選ばれた横幅はコンテンツが丁度入るくらいのサイズで親ビュー(Frame)の真ん中にポンと置かれています。

縦幅が足りない時でも切り捨てが起きることがあります。

struct ContentView : View {
    var body: some View {
        Text("Nogitsune Takeshi")
            .font(.title)
            .frame(width: 200, height: 50)
    }
}

行数が限られてないとしても提案サイズの縦幅が1行しか入らないのでこの例でコンテンツが提案サイズに合わせてます。

text_frame_truncation.png

リサイズ可能な画像

ビューが自分のサイズを選ぶときに柔軟に選べることはわかった上でもう一度Imageを見てみましょう。

普段Imageは画像ファイルの解像度のサイズになりますが、リサイズすることもできます。

struct ContentView : View {
    var body: some View {
        Image("barbarian")
            .resizable()
            .frame(width: 200, height: 150)
    }
}

リサイズ可能なImage(リサイザブル)は親ビューからもらった提案サイズそのまま選んでできるだけスペースを埋むようにします。

resizable_image.png

デフォルトでImageは画像を伸ばしてスペースを埋むけど.resizable(resizingMode: .tile)を使うと画像をリピートすることができます。

struct ContentView : View {
    var body: some View {
        Image("barbarian")
            .resizable(resizingMode: .tile)
            .frame(width: 200, height: 150)
    }
}

ImageのサイズはまだFrameからもらった提案サイズのままなのですが、単に画像を複数回描画しているだけに注意。

tile_image.png

アプリつくっているとき、画像を伸ばすのも複数描画のも違う単純に「変に伸ばさずこのサイズで一番大きいサイズで画像を表示したい」だけの時が多いと思いますが、その時は.aspectRatioという便利なmodifierもあります。.aspectRatio.resizableと一緒に使うことでアスペクト比変わらずリサイズをすることが可能になります。

Modifierの順番

複数なmodifierを使うときは順番は重要です。各modifierがそのmodifierが使われたビューに適応されるのでSwiftUIのmodifierは逆の順番に書かれるのです。

ポイント!!SwiftUIのmodifierは逆の順番に書かれるのです。

ソース画像のアスペクト比で正しくframeのサイズに合わせたImageを作るのに以下の順番でmodifierを書く必要があります。

struct ContentView : View {
    var body: some View {
        Image("barbarian")
            .resizable()
            .aspectRatio(contentMode: .fit)
            .frame(width: 200, height: 150)
    }
}

このコードでは.resizableはImageに追加されました。ってことはImageは.resizableのチャイルドになります。.frameと同じように。

そのあとは第2のmodifier、.aspectRatioを追加することによってaspectRatioは「リサイザブル画像」に適応されて、「リサイザブル画像にアスペクト比を適応する」という流れなので、modifierチェーンの最後に追加します。

そして最後に「アスペクト比を使うリサイザブル画像」をframeに打ち込みたいので最後に.frameを追加。大事なポイントはチェーンの最後にframeは来てますがビューの構成ではframeは一番最初のビューになります。

そしてそれで正しく表示できます→

aspectratio_image.png

ソース画像と親ビューの提案サイズを参考にして、Imageが親が渡したheightを使おうとしましたが、元画像のheightが足りないので元画像のサイズを大きくしてheightを選び、アスペクト比が変わらないためのwidthを計算して選んで、サイズを決定しました。

親の横幅が大きすぎて子ビューが全部使わないので真ん中に置くことになりました。

こういったルールを理解した上で複数ビューをstackで合体することやflexible frameの奇妙なケースなどを確認できるでしょう!

Imagery used in previews by Kaiseto, original images and derived here licensed under Creative Commons 3.0 BY-NC-SA.

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