20200623のiOSに関する記事は11件です。

cocoapodsでsdwebimageをinstallしたのにNo such moduleって出るときの対処法

症状

cocoapodsでライブラリ(sdwebimage)をインストールしたのに,importしようとするとNo such moduleとエラーが表示される

対処法

よくあるエラーらしい.いくつか対処法があるらしいが,
私は以下で解決した

ステップ1

ワークスペース(拡張子が.xcworkspaceのやつ)を消す

ステップ2

ターミナルでワークスペースがあった階層まで行きpod installを実行する
これで治るはず
参考
https://stackoverflow.com/questions/54683959/no-such-module-sdwebimage-using-pod

私は治らなかった対処法

https://qiita.com/sukkuuuuu/items/47574f1a4dd3f92aa0bb

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

Cycle GANをCoreMLモデルに変換

horse2zebra_1.png

*論文:サイクルでつながった敵対的ネットワークを使用するペアになっていない画像から画像への変換

CoreMLに変換することでCycleGAN画像変換をiPhoneアプリで使用できます。

このストーリーでは、TensorFlow CoreのCycleGANチュートリアルモデルを使用します。

最初に、Colaboratoryでチュートリアルモデルをトレーニングします。

colabの以下のセルまでの全てのセルを実行します。

colab
for epoch in range(EPOCHS):
  start = time.time()

  n = 0
  for image_x, image_y in tf.data.Dataset.zip((train_horses, train_zebras)):
    train_step(image_x, image_y)
    if n % 10 == 0:
      print ('.', end='')
    n+=1

  clear_output(wait=True)
  # Using a consistent image (sample_horse) so that the progress of the model
  # is clearly visible.
  generate_images(generator_g, sample_horse)

  if (epoch + 1) % 5 == 0:
    ckpt_save_path = ckpt_manager.save()
    print ('Saving checkpoint for epoch {} at {}'.format(epoch+1,
                                                         ckpt_save_path))

  print ('Time taken for epoch {} is {} sec\n'.format(epoch + 1,
                                                      time.time()-start))

モデルのトレーニングが完了したら、新しいセルを挿入して以下の手順で変換を実行します。

1、TFCoreMLをインストールします。

colab
!pip install --upgrade tfcoreml

2、チェックポイントを復元します。

colab
checkpoint_path = "./checkpoints/train"

ckpt = tf.train.Checkpoint(generator_g=generator_g,
                           generator_f=generator_f,
                           discriminator_x=discriminator_x,
                           discriminator_y=discriminator_y,
                           generator_g_optimizer=generator_g_optimizer,
                           generator_f_optimizer=generator_f_optimizer,
                           discriminator_x_optimizer=discriminator_x_optimizer,
                           discriminator_y_optimizer=discriminator_y_optimizer)

ckpt_manager = tf.train.CheckpointManager(ckpt, checkpoint_path, max_to_keep=5)

# if a checkpoint exists, restore the latest checkpoint.
if ckpt_manager.latest_checkpoint:
  ckpt.restore(ckpt_manager.latest_checkpoint)
  print ('Latest checkpoint restored!!')

3、「saved_model」フォーマットでジェネレータg(これがhorse2zebraジェネレーターです。ジェネレーターfはzebra2horse)を保存します。

colab
generator_g.save './ savedmodel'

4、変換を実行します。

import tfcoreml
input_name = generator.inputs[0].name.split(':')[0]
print(input_name) #Check input_name.
keras_output_node_name = generator_g.outputs[0].name.split(':')[0]
graph_output_node_name = keras_output_node_name.split('/')[-1]
mlmodel = tfcoreml.convert('./savedmodel',
                       input_name_shape_dict={input_name: (1, 256, 256, 3)},
                       output_feature_names=[graph_output_node_name],
                       minimum_ios_deployment_target='13',
                       image_input_names=input_name,
                       image_scale=2/ 255.0,
                       red_bias=-1,
                       green_bias=-1,
                       blue_bias=-1,
                       )
mlmodel.save('./cyclegan.mlmodel')

これで、iOSプロジェクトでCycleGANを使用できます。

import Vision
lazy var coreMLRequest:VNCoreMLRequest = {
   let model = try! VNCoreMLModel(for: cyclegan().model)
   let request = VNCoreMLRequest(model: mode, completionHandler: self.coreMLCompletionHandler0)   
   return request
   }()

let handler = VNImageRequestHandler(ciImage: ciimage,options: [:])   

DispatchQueue.global(qos: .userInitiated).async {   
  try? handler.perform([coreMLRequest])
}

multiArrayを画像として視覚化するには、Hollance氏のCoreML Helpersが非常に便利です。

MultiArrayからImageへの変換 CoreMLHelper

自分でデータセットを用意してトレーニングすれば何2何でも作れます!

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

iPhoneアプリ学習:診断画面

はじめに

某プログラミング学習サイトでの学習記録を記します。

共通操作

・範囲選択:Shiftを押しながらクリック
・複数行コメントアウト:Command /

No1:プロジェクト作成

・Single View

No2:画面

・Main.storyboardを選択
・画面上の三つのアイコンの左端を選ぶ(ViewController)
・Editor > Embed In > Navigation Controllerを選択
 (Navigation Controllerは画面遷移に必要)
・View ControllerのNavigation itemのTitleに題名を入力する
・名前を入力するためのText Fieldとそれを送信するためのButtonを配置する

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

何故かUIScrollViewの正しいサイズが取れない

問題

何故か、UIScrollViewのサイズ(scrollView.bounds.size)が正しい値が取れないことがあった。

値を見てみると、AutoLayoutが作用する前の値が返ってきているようだった。

対処

  • viewDidLayoutSubviewsメソッドを使う
    • 意図したサイズ(AutoLayoutが作用した後のサイズ)を取ることができた。
override func viewDidLayoutSubviews() {
    super.viewDidLayoutSubviews()

    //UIScrollViewのサイズ取得
}

ただ、viewDidLayoutSubviewsはViewControllerのライフサイクルの一員ではないので、何度でも呼ばれる可能性がある。普通に書いただけで二度呼ばれていたし、画面を回転させた時も呼ばれるのでは?

  • lauoutIfNeededメソッドで強制的にレイアウトを行う
    • 意図したサイズ(AutoLayoutが作用した後のサイズ)を取ることができた。
        //scrollviewの正しいサイズを取得するため、レイアウトを行う。
        self.view.setNeedsLayout()
        self.view.layoutIfNeeded()

        //UIScrollViewのサイズ取得

viewDidLayoutSubviewsは何度も呼ばれる点が不便だったため、lauoutIfNeededを採用した。

更なる課題

UITableView、UICollectionViewなどUIScrollViewのサブクラスではこのような問題は経験上起きないと思うが、何故UIScrollViewでのみこういった問題(オートレイアウトがされていない)が起きるのかよく分からなかった。

参考

https://stackoverflow.com/questions/12527191/ios-autolayout-get-frame-size-width/14147303#14147303

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

[Swift] Storyboard プロトタイプセルの使い方

プロトタイプセル

Storyboard上でUITableViewやUICollectionViewを設置した際、さらにプロトタイプセルも設置できる。(オブジェクトの追加ボタン(+ボタン)から、table view cellや collection view cellを選ぶ)

セルそのものは、reuseIdentifierを使うことにより、コード上で識別できる。

プロトタイプセルの中身

プロトタイプセル内に自分で設置した部品(例えばUIImageViewやUITextFieldなどなど)は、Story Board上でタグの数値を指定することで、コード上で識別できるようになる。ViewControllerのviewWithTag()メソッドを使う。

参考

[iPhone] UITableView をストーリボードで作る

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

技術的負債を解消するには(iOS開発)

技術的負債がたまるとはどういう状態か

読みにくいコード、複雑なコード(Cruft)は、何も考えなくてもかける為、一応実装のスピードは出る。しかしそれも短期的なもので、時間が経つに連れて負債がたまる。具体的には、ある部分に修正の必要があったり、追加機能が必要な際に、既存のコードを読み解いたりするのに余計な時間がかかってしまう。

どのような方針で対応すべきか

すでにコーディングした部分に修正をくわえる場合

技術的負債を解消するにもコストはかかる。その為、コストとリターンを秤にかけて決定する。

例えば、将来あまり使わなそうなプロジェクトであれば修正をする意味はあまりない。

またプロジェクト内部において、将来あまりいじらない部分のモジュールであれば同じく修正をする意味はあまりなくなる。具体的には、独立性の高い部分のコードなど。

またやるにしてもどの程度やるかの問題がある。全体に対して完璧になるまで修正をすると何ヶ月もかかりかねず、過剰な措置ともなりかねない。他方、全部後回しにしては、前述のようにどんどん負債が大きくなっていってしまう。その為、コーディングする都度、関係する部分を少しずつ直し、自分が見る前よりも少し綺麗なコードにする(ボーイスカウトルール)など、日々少しずつ解消していくのが有効な場合が多いと言える。

これからコーディングをする場合

そもそも技術的負債が発生しないように最初にコーディングするのが一番効率が良い。また知見と技術力さえあれば、そのようなコーディングをしつつ、かかる時間もさほど増やさないようにするのは不可能ではない。

その為、そのような知見を積極的に吸収し、コーディングをするときから積極的に実行していくのが良い。

参考文献

https://note.com/timakin/n/nf7e2a70905d4
https://qiita.com/erukiti/items/9cc7850250268582dde7
http://tlync.hateblo.jp/entry/2014/09/28/025652
https://martinfowler.com/bliki/TechnicalDebt.html
https://medium.com/mop-developers/how-to-manage-technical-debt-961f8f94a623

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

iOSでステータスバーの背景色を変える拡張関数(Swift)

はじめに

iOSでは、ステータスバーの背景色を単体でかんたんに変えることができません。
UIViewController#view.backgroundColor を指定するとステータスバーの背景色が変わりますが、同時にビュー全体の背景色も変わってしまいます。

いくつか方法はあるのですが、今回は「上左右をSuperviewに合わせ、下をSafe Areaの上に付けたビュー」を追加することで実現します。
Storyboardを作成するたびに手動でビューを追加するのは手間なので、呼び出すだけでステータスバーの背景色を変えられる拡張関数を実装しました。

環境

  • OS:macOS Mojave 10.14.6
  • Xcode:11.3.1 (11C504)
  • Swift:5.1.3
  • iOS:13.3

実装

UIViewController に拡張関数を追加します。

UIViewController+StatusBar.swift
import UIKit

extension UIViewController {
    private final class StatusBarView: UIView { }

    func setStatusBarBackgroundColor(_ color: UIColor?) {
        for subView in self.view.subviews where subView is StatusBarView {
            subView.removeFromSuperview()
        }
        guard let color = color else {
            return
        }
        let statusBarView = StatusBarView()
        statusBarView.backgroundColor = color
        self.view.addSubview(statusBarView)
        statusBarView.translatesAutoresizingMaskIntoConstraints = false
        statusBarView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
        statusBarView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
        statusBarView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
        statusBarView.bottomAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor).isActive = true
    }
}

複数回呼ばれてもビューが重ならないよう、処理の最初で StatusBarView があったら剥がすようにしています。

使い方

UIViewControllerviewDidLoad() で色を指定して呼び出すのみです。

FooViewController.swift
final class FooViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        configureView()
    }

    private func configureView() {
        setStatusBarBackgroundColor(.blue)
    }
}

ノッチの有無にかかわらず、ステータスバーの背景色が変わります。

iPhone 8 iPhone 11 Pro Max
Simulator Screen Shot - iPhone 8 - 2020-06-23 at 15.17.25.png Simulator Screen Shot - iPhone 11 Pro Max - 2020-06-23 at 15.27.39.png

参考リンク

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

ダークモード対応時にObjective-Cのコードがあったとき

はじめに

歴史のあるiOSアプリのプロジェクトになると、Swift移行が完全でなくObjective-C(以降、objc)のコードが残存していたりするかと思います。

自分の関わるプロジェクトでは、ダークモード対応するぞ!ってなったときに、objcのコードが残っていたので一部objcで対応しました。

コードから直接カラーセットを利用する

Storyboard上のパーツにカラー指定すれば基本的には対応できますが、中にはコード上でカスタムカラーを指定している場合もあります。

Swiftで記述する場合はenumでカラーセットを定義してそれを利用するとか、UIColorのextensionでカスタムカラーを定義する方法があるかと思います。

自分の関わったプロジェクトでは前者の方法で対応していたため、objcでenumを使えませんでした。
objc用で列挙型を定義するのもありかもしれませんが、いずれobjcを撲滅することを考えるとわざわざ定義するのに工数もかけたくありません。
直接呼び出せればいいやって感じです。

その時は以下のようにします。

// ラベルの文字色を決めるとき
textLabel.textColor = [UIColor colorNamed: @"hogehoge"];
// 画像の枠の色を決めるとき
imageView.layer.borderColor = [[UIColor colorNamed: @"hugahuga"] CGColor];

一応、Swiftだとこんな感じになります。

// ラベルの文字色を決めるとき
textLabel.textColor = UIColor(named: "hogehoge") ?? UIColor.black
// 画像の枠の色を決めるとき
imageView.layer.borderColor = UIColor(named: "hugahuga").cgColor ?? UIColor.black.cgColor

意外と簡単にカラーセット呼び出せるんですね。
早くobjc撲滅してSwiftで綺麗にしたい。

ライトモードとダークモードの切り替え時の対応

traitCollectionDidChangeを利用して、モードが切り替わったことを検知して、そのときにカスタムカラーの更新をかけます。

- (void)traitCollectionDidChange:(UITraitCollection *)previousTraitCollection
{
    [super traitCollectionDidChange:previousTraitCollection];

    if (@available(iOS 12.0, *)) {
         UIUserInterfaceStyle currentStyle = self.traitCollection.userInterfaceStyle;
         UIUserInterfaceStyle previousStyle = previousTraitCollection.userInterfaceStyle;

        if (currentStyle != previousStyle) {
            //カスタムカラーの更新処理を記述する
        }
    }
}

Swiftでも基本的に同様の書き方です。

override func traitCollectionDidChange(_ previousTraitCollection: UITraitCollection?) {
    super.traitCollectionDidChange(previousTraitCollection)

    if #available(iOS 12.0, *) {
        let previousStyle = previousTraitCollection?.userInterfaceStyle
        let currentStyle = traitCollection.userInterfaceStyle

        if previousStyle != currentStyle {
            // カスタムカラーの更新処理を記述する
        }
    }
}

参照

  1. colorNamed: - UIColor | Apple Developer Documentation
  2. iOS13 ダークモード対応
  3. 爆速でiOSアプリのカラー設定をするための`extension`と`enum`
  4. Objective-Cのアプリをダークモード対応した
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

WWDC 2020 keynote:動画配信の視点で気になった点

AppleのWWDC 2020 (https://www.apple.com/apple-events/june-2020/ )の基調講演を見て、動画配信の目線で気になった点を簡単にまとめておきます。

Picture in Picture機能がiOSにも追加

元々、既にiPadOSでは搭載されていた機能ですが、iOS 14からiPhoneでもPicture in Pictureが使えるようになります。
ネイティブのプレイヤーを利用していれば、問題なく使えると思いますが、サービスのコンセプトやコンテンツフォルダーとの許諾の関係上、そもそも許可したくない場合なども考えられますので、注意が必要です。

iOS/iPadがApple SiliconのmacOSで動く

※SoCやらCPUの知識が乏しいため、不確かなことを書いていたらご指摘ください。

元々、昨年のmacOS Catalinaから、Mac CatalystでiPadアプリケーションをmacOSに提供することはできましたが、あくまでiPadアプリをmacOS向けに変換するものでした。

Apple SiliconはiPhone/iPadと同系のSoCになりますので、おそらくアプリの変換なく利用できるようになるはずです。

ストアの設定でmacOS向けに公開するかどうかの選択くらいはできると思いますが、macOSに対して展開した場合に

  • 権利の許諾関係に問題はないか
  • DRMが正しく動作するか
  • アプリの画面サイズはどういう扱いになるか(自由になると厄介ですね)

など、色々と検証が必要そうです。

macOSはしばらくの間、Intel系とApple Silicon系が並行して存在する

Apple Silicon搭載のMacは2020年末に発売予定で、2年間の移行期間があるようです。
移行期間の意味をどうとらえるか悩みどころですが、メジャーアップデートが2年という意味で、Intel Macのシェアがすぐ縮小するとは思えません。

同じmacOSと言えど、Intel MacとApple Siliconの挙動が完全に一致はしないのは間違いないでしょう。特にSafariでの動画再生は両方の検証をしておく必要がでてくると思われます。

参考)アップル、MacのCPUを「Apple Silicon」に。年内に最初の製品、2年で切替
https://www.watch.impress.co.jp/docs/news/1260710.html

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

[Swift] iOS13以降で使用可能なAPIまとめ

iOS APIとは?

Appleにより提供されている標準APIです。
意外と知られていない面白い機能などがたくさんあるので、今日はいくつかピックアップして紹介します。

環境

  • Xcode11.1
  • Swift5

Vision(Text Recognition)

68022429-9b05bc00-fce7-11e9-8337-fa71db61583a.gif

概要:
・文字の領域を識別
・文字認識

※英数字の識別しか現状できない

技術資料:
How to use VNRecognizeTextRequest’s optical character recognition to detect text in an image
Text recognition on iOS 13 with Vision, SwiftUI and Combine

サンプルコード:
ScanningDocuments

Apple Document:
https://developer.apple.com/documentation/vision

VisionKit

68005518-e05ec500-fcb8-11e9-802d-4f732efee9df.gif
概要:
・iOS13からNotesアプリに搭載されるOCRの機能を提供(文字認識)
・ドキュメントスキャン
・ドキュメント編集

技術資料:
VisionKitBasics
Scanning documents with Vision and VisionKit on iOS 13

サンプルコード:
VisionKit-Example

Apple Document:
https://developer.apple.com/documentation/visionkit
https://developer.apple.com/documentation/visionkit/vndocumentcameraviewcontrollerdelegate

Core NFC

68223032-60758980-002f-11ea-8fb2-559f9c451b69.gif
概要:
・NFCタグ直接読み取り/書き込み(システムコード指定、暗号化通信可)
・カード固有IDの読み出し
・高機能/複雑な構造を持ったカード・タグの取り扱い
・交通系電子マネーの履歴読み取り
・会員カードの読み取り
・NDEFタグの作成・書き換え
・フィットネス機器などとの双方向の通信
・各種機器の設定
・各種機器のそれなりの容量のデータの読み取り

※ FeliCa Plug, FeliCa Linkその他など

技術資料:
iPhoneでFeliCaを読み取ってみた
iOS13 CoreNFCの使いみちとQRコード、BLEとの比較

サンプルコード:
vCardCoreNFCWriter

ライブラリ:
TRETJapanNFCReader

Apple Document:
https://developer.apple.com/documentation/corenfc

Portrait Effects Matte

68223058-6c614b80-002f-11ea-8e2e-0600ab35794b.png
概要:
・人物の矩形を背景から切り抜き
・人物の矩形と背景の深度測定
・AR表現における回り込み

※現状静止画のみ
※人物のみ

技術資料:
iOS 12のPortrait Matteがすごい/ #iOSDC 2018で登壇します

サンプルコード:
PortraitEffectsMatteSample

Apple Document:
https://developer.apple.com/documentation/avfoundation/avportraiteffectsmatte

Semantic Segmentation Matte

68005658-4fd4b480-fcb9-11e9-800b-c6d109cf0387.jpg
概要:
概要:
・人物の"髪", "肌", "歯"をセグメンテーションする

※現状静止画のみ
※人物のみ

技術資料:
Multi-cam support in iOS 13 allows simultaneous video, photo, and audio capture

Apple Document:
https://developer.apple.com/documentation/avfoundation/avsemanticsegmentationmatte?language=objc

補足:
Portrait Effects Matteと同様の方法でImageDataを操作するが、用意されているメソッドでは今の所実装出来なかった(動かなかった)。 Semantic Segmentation Matteの実装資料も見当たらない。 またApple公式でもSemantic Segmentation Matteの実装について言及している資料が見当たらない。

Core Haptic

68066465-ef5a7b80-fd7b-11e9-8fad-812ae63b4af5.jpg
概要:
・デバイスの振動制御が可能
・細かな振動制御まで可能

技術資料:
iOS13で公開予定の「Core Haptics」を使って、Haptic Feedback (触覚フィードバック) するコードを書いてみた

Apple Document:
https://developer.apple.com/documentation/corehaptics

デプス推定(Apple提供CoreML)

68222674-b85fc080-002e-11ea-99f8-551d11973736.gif
概要:
・iOS11以上であればどのデバイスでも測定可能
・静止画でも動画でも測定可能
・人間以外のオブジェクトも識別可能 ・Depth測定以外(セグメンテーション)なども可能
・Portrait Effects MatteやSemantic Segmentation Matteなど、iOS13以降の標準APIよりかは精度は荒い印象(学習モデルが強化されたら今後の期待大)

技術資料:
DepthPrediction-CoreML

Apple Document:
https://developer.apple.com/jp/machine-learning/models/

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

Flutter duplicate symbols for architecture x86_64

Flutter duplicate symbols for architecture x86_64の解決

34 duplicate symbols for architecture x86_64

    ld: 34 duplicate symbols for architecture x86_64
    clang: error: linker command failed with exit code 1 (use -v to see invocation)
    note: Using new build system
    note: Building targets in parallel
    note: Planning build
    note: Constructing build description

これが出たときの対処法。

いつ起こったか

Flutterをiosで起動させようとした時に起こりました。

原因

FlutterのプロジェクトがiCloud内のディレクトリで作られている時に起こることがあるらしいです。
エラー通りいろんなファイルが二重で作成されてしまいエラーが起こるというのが原因。

解決方法。

1. 二重で作成されたファイルを消去してあげる。

find . -name \*\ 2.\* //間違えたファイルを消さないように一度確認する。
find . -name \*\ 2.\* -delete
flutter clean
flutter run

とりあえず余分に作成されてしまったファイルを消去するという方法。
(たくさんファイルが出てくると思いますが間違えて必要なファイルを消してしまわないように気をつけてください。)
必要があれば上記の2->3でもやってみる。
自分はこれだけでで解決したのですが、解決しない人は以下を試してみるといいかも...

2.podsを再インストールしてみる。

cd ios
pod deintegrate
cd ..
flutter clean
flutter run

最後に

Flutterやっていると自然と英語のドキュメントとか海外のサイト等見ることになる=> 癖がつくのでいい練習になるなって思います。(日本語充実してる言語だとどうしてもそっちに逃げちゃいますよね...)

参考

Duplicate Symbols with IOS Build

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