[iOS] シングルトンでRxSwiftのSingle使ってメモリリークはどうなるのか調べた | Singleton

2020/05/3

こんにちは。きんくまです。

RxSwiftのメモリリークがどうなるのか気になったので調べてみました。
RxSwiftのバージョンは5.0.1

まずは実際のメモリリークをみてみます

こんな感じにメモリリークのマークが出ていることがわかります。ただし、これはSingleではなくてObservableを使っておこしています。理由はあとで説明。

前提

どういうときにおきるのか?いろいろと調べてみたのですが、通常は2点あります。

1. .disposed(by: disposeBag) を呼んでいない
2. クロージャーの中で weak self を使わずに self を使って循環参照をおこしてしまっている

逆にどういうときにObservableのメモリが開放されるかというと以下のとき

1. .onCompleted()を呼んだとき
2. .onError(error)を呼んだとき

参考)【RxSwift】Singleton で DisposeBag を使うことの考察

この投稿の続きを読む »

LINEで送る
Pocket

[iOS] Xcode ServerのBotがArchiveは成功するけどProductが失敗してipaを作れないとき

2020/01/4

こんにちは。きんくまです。
またXcode Serverのやつです。

Xcode 11です。
Release設定をAd Hoc用にしておいた後、BotがIntegrateを開始します。
テストもしてArchiveも作ったけど、次のようなエラーが出てipaができずに困っちゃうときです。

Bot Issue for SampleTest Bot (error)
Integration #15 of SampleTest Bot on MacBookPro2018
Open Integration in Xcode: xcbot://MacBookPro2018/botID/00e14b3ed5186425a89a18ceed000ef4/integrationID/00e14b3ed5186425a89a18ceed063001
Build Service Error: exportArchive: "SampleTest.app" requires a provisioning profile.
Introduced 5 integrations ago

Signingはこんな感じに、ReleaseをAd Hoc用にしてあります。

調べたら、こちらのページに書いてありました。

Assertion: exportArchive: “Test.app” requires a provisioning profile

ExportOptions.plistを設定してあげればいいみたい。
さっそく設定しましょう。Edit Botすると出てくるダイアログのConfigurationをみます。

Use Custom Export Options Plistを選択します。
するとセットでExportOptions.plistというファイルを見せないといけないです。でもこれって何のファイルなの?

と思ったら、一度Ad Hoc用に書き出せば元ファイルが得られるとのこと。
なのでAd Hoc用に書き出します。そして書き出されたフォルダの中身を見ると、確かにExportOptions.plistというファイルがありました。

このファイルをさきほどの設定部分で設定してあげます。

すると無事にipaが書き出されました。LAN上のiPhoneからもインストールすることができました。

LINEで送る
Pocket

[iOS] Xcode ServerでBot作ったあとにブラウザで見ようとしたらChromeのセキュリティエラーになったときの対処方法

2020/01/3

こんにちは。きんくまです。
Xcode Serverやっている人がいるのかどうかわからないので誰得情報なの?だと思うのですが、メモ書きです。

Xcode ServerでView Bot in Browserを選んだら、ChromeでSSL証明書が信頼されていなくてページがみられなくなったときの対処法です。

Xcode ServerでBotを作ります。
右クリックすると、View Bot in Browserを選べます。

この投稿の続きを読む »

LINEで送る
Pocket

[日記] 2019年 ふりかえり

2019/12/31

こんにちは。きんくまです。
2019年の今年何をやったかを書きます。忘れっぽいのでメモみたいな。

会社員になった

1月にフリーランスから会社員になりました。
>> モバイルアプリサービス部にジョインした きんくま です

いまは部署名が変わってCX事業本部というところになっています。

フリーランスは11年やってました。ほとんど家で受託開発してました。
なので会社員生活、電車通勤とかチームでの開発とかいろいろと大丈夫かなとも思ったのですが、何とかなりました。

基本毎日出勤して、リモートは週1ぐらいでやってます。
リモートは出勤がなくて便利なんですが、会社にいるチームメンバーに気を使ったりするところもあり、そんなに多くしてません。
SlackやGoogle Meetとかあるけど、なんだかんだでリアルで顔合わせて話した方がやりやすいと思います。あとはある程度対面で親しくなってからリモートをやる方が、距離感がつかめて良いかな。

この投稿の続きを読む »

LINEで送る
Pocket

[iOS] 配列をソート(並び替え)したい | Array, sort, sorted

2019/07/20

こんにちは。きんくまです。

配列のソート(並び替え)があやふやだったので、調べてみました。

sortとsorted

配列には sort と sorted があります。

sort
sortは配列の中身を変更します。

        var intArr = [10, 5, 3]
        intArr.sort()
        print("\(intArr)") // [3, 5, 10]
        
        var strArr = ["b", "c", "a"]
        strArr.sort()
        print("\(strArr)") // ["a", "b", "c"]

sorted
sortedは配列の中身を変更しないで、ソートされた新しい配列を返します

        let intArr = [10, 5, 3]
        let sortedIntArr = intArr.sorted()
        print("\(intArr)") // [10, 5, 3] 元のまま
        print("\(sortedIntArr)") // [3, 5, 10] ソートされてる
        
        let strArr = ["b", "c", "a"]
        let sortedStrArr = strArr.sorted()
        print("\(strArr)") // ["b", "c", "a"] 元のまま
        print("\(sortedStrArr)") // ["a", "b", "c"] ソートされてる

最近の関数型プログラムの流行からすると、元の配列を変更せず変更後のものを返す sorted を使うのが良さそう。

この投稿の続きを読む »

LINEで送る
Pocket

[iOS] Xcode 10.2 / iOS SDK 12.2 | Codableで Dictionary型のキーはキャメルケースに変換されない

2019/06/6

こんにちは。きんくまです。

Swift5はXcode10.2から使用可能で、先日アップデートしました。
それで、Xcode10.2でJSONからオブジェクトに変換するときの挙動がちょっと変わっていたので、共有です。


struct Sample: Codable {
    var keyName1: String?
    var keyName2: [String: String]?
    var keyName3: Child?
    
    struct Child: Codable {
        var chKeyName1: String?
        var chKeyName2: [String: String]?
        var chKeyName3: GrandChild?
    }
    
    struct GrandChild: Codable {
        var gcKeyName1: String?
        var gcKeyName2: [String: String]?
    }
}

        let jsonText = """
{
    "key_name1": "hello1",
    "key_name2": {
        "sub_child1": "hello2",
        "sub_child2": "hello3"
    },
    "key_name3": {
        "ch_key_name1": "hello4",
        "ch_key_name2": {
            "sub_child3": "hello5",
            "sub_child4": "hello6"
        },
        "ch_key_name3": {
            "gc_key_name1": "hello7",
            "gc_key_name2": {
                "sub_child5": "hello8",
                "sub_child6": "hello9"
            }
        }
    }
}
"""

        let decoder = JSONDecoder()
        decoder.keyDecodingStrategy = .convertFromSnakeCase
        let textData = jsonText.data(using: .utf8)!
        do {
            let decodedSample = try decoder.decode(Sample.self, from: textData)

            //Xcode10.1まではこれでいけたのに、Xcode10.2だと空になる
            decodedSample.keyName2["subChild1"] // nil

            //Xcode10.2からはこちら
            decodedSample.keyName2["sub_child1"] // "hello2"

            //同様に辞書部分はキャメルケースでアクセス
            decodedSample.keyName3?.chKeyName3?.gcKeyName2?["sub_child5"]
        } catch let error {
            print("error \(error)")
        }

これについてテストしました。

Child型やGrandChild型といった型を定義したものであれば、JSONのプロパティ名がスネークケースのものが型のキャメルケースプロパティに入ります。(従来のまま)

ネストの状況も2階層、3階層とあってもしっかり変換されました!

しかし!型を定義していない辞書型の [String:String] とかだと、キーはキャメルケースに変換されずにスネークケースのままになります。OH!

しれっと、重要なところ変えてきたよリンゴさん!これで動かないアプリいっぱいあると思うよ!
リリースノートにも書いてなかったよw

参考)
Dictionary keys are no longer converted using keyDecodingStrategy under Xcode 10.2

LINEで送る
Pocket

[iOS] ベースクラスのextensionを、protocolで実装する話

2019/05/29

こんにちは。きんくまです。

Swiftのextensionは大変便利で、いろいろなクラスに対して拡張実装を作ることが可能です。

例えば

extension UIViewController {
    func showAlert(title: String?, message: String?, callback: @escaping () -> Void) {
        let alertController = UIAlertController(title: title,
                                                message: message,
                                                preferredStyle: .alert)
        let okAction = UIAlertAction(title: "OK",
                                     style: .default) { action in
            callback()
        }
        let cancelAction = UIAlertAction(title: "Cancel",
                                         style: .cancel,
                                         handler: nil)
        alertController.addAction(okAction)
        alertController.addAction(cancelAction)
        present(alertController, animated: true, completion: nil)
    }
}

こんな感じに、UIViewControllerに対して、アラートを出すことができるメソッドを定義することができます。

ただ、個人的にはこういう全ての場面で共通で使いそうなクラス(この場合UIViewController)に対して拡張を書くというのが、気になるなーと思いました。どこが気になるかというと、

– クラスを拡張していることが、クラスの定義のところを見るだけだと気づかない
– 使う必要のないクラスにも適用されてしまう

という感じでしょうか。例えば、上のコードだと、アラートを出す必要のないUIViewControllerにも拡張されてしまいます。

この投稿の続きを読む »

LINEで送る
Pocket

ページトップへ戻る