一畳のくつろぎタイム

このブログでは紹介する商品画像をAmazonアソシエイトより借りています。画像やリンクにはアフィリエイト広告が含まれる事があります
ラベル iOS の投稿を表示しています。 すべての投稿を表示
ラベル iOS の投稿を表示しています。 すべての投稿を表示

2018年9月20日木曜日

UITabBarControllerでタブがありすぎる時の挙動

AppleのUITabBarControllerの説明に以下のようにある。

The tab bar has limited space for displaying your custom items. If you add six or more custom view controllers to a tab bar controller, the tab bar controller displays only the first four items plus the standard More item on the tab bar. Tapping the More item brings up a standard interface for selecting the remaining items.

かいつまんで日本語にすると、タブバーは6個目からは配置するスペースがないので、最初の4つだけ出て、他はMoreになるよ。
 ということである。もうちょっと書いてあるが、上3行ぐらいでとりあえず知りたいことはわかった。最後の行が何を言ってるのかよくわからなかったが試したらよくわかった。

 Moreをアクションシート的なものを想像していたら全然違ったので、記事にしています。

検証としてはタブを10個用意。
わかりやすいように背景色をランダムに生成し、ボタンを配置して画面の番号を表示しています。


 Moreを押すと、入りきらなかった画面4〜画面9タブの名前が入ったテーブルビューが登場。選ぶとその画面にいけるが、自動的にナビゲーションバーのようなものが付属する。
最初の4タブについては、余計なものはついてこない。しかもEdit機能があり最初の4タブとの入れ替えが可能だという。

使う機会はないと思うが、面白い挙動だった。

検証で使用したコードはこちら
https://github.com/snowfoxj/TabBarControllerTestCode

2018年9月5日水曜日

SwiftのOptionalがうざいところ

Swiftのオプショナルがうざい

なにがうざいかと言うと、なかったら作る処理が簡潔に書けない。

コードオンリーでUITableViewを作っていると、UITableViewCellを作るときにdequeueReusableCellメソッドがnilを返した場合に新しくインスタンスを作り、nilでなければメソッドより返された値を使う。
??演算子を使用すれば、それに近いことはできる。だがしかし、新たに作成したUITableViewCellの初期設定がしたいのだ。??の後ろが1行じゃ足りなくて、もう少し行が欲しい。
        let cell:UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "hoge") ?? UITableViewCell(style: .default, reuseIdentifier: "hoge")
Objective-Cの場合、至ってシンプルである。nilだったら作って設定すればいい。
- (nonnull UITableViewCell *)tableView:(nonnull UITableView *)tableView cellForRowAtIndexPath:(nonnull NSIndexPath *)indexPath {
    
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"hoge"];
    
    // 再利用セルがない場合は
    if( cell == nil ) {
        // 作成する
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"hoge"];
        // ここで作ったcellの共通設定
    }
    
    // ここで内容の更新処理
     
    return cell;
}



Swiftの場合、guard文だと処理の中断が必須なため。guard文の中と外で2回内容の更新処理を書かなくてはならなくなる
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "hoge") else {

            let cell = UITableViewCell(style: .default, reuseIdentifier: "hoge")
            
            // 初期設定

            // 内容の更新処理
            
            return cell
        }


        // 内容の更新処理
        

       return cell
    }

オプショナルバインディングだと大した処理がないのに、代入のためだけのif-else両方が必要になる
        let cell:UITableViewCell
        
        if let unwrappedCell = tableView.dequeueReusableCell(withIdentifier: "hoge") {
            cell = unwrappedCell
        } else {
            cell = UITableViewCell(style: .default, reuseIdentifier: "hoge")
            // 初期設定
        }

        // 内容の更新処理

        return cell
外のスコープに変数を用意するぐらいだったら、オプショナルバインディングなどいらぬ。
以下のようにオプショナル構文を使わないで書いたって同じことだ。
        // セルの再利用可能か取得して見る
        let optCell:UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: "hoge")
        
        let cell:UITableViewCell
        
        if optCell == nil {
            cell = UITableViewCell(style: .default, reuseIdentifier: "hoge")
            
            // 初期設定をする
            
        } else {
            // アンラップする
            cell = optCell!
        }
        
        // 内容の更新処理をする
        
        return cell
わずかではあるが、変数を2個用意しないで済むオプショナルバインディングを使った方が簡潔なのがなんか腹立たしい。

内容の更新処理をメソッド化すれば2回同じことは書かないで済むし、UITableViewCellのサブクラスを作れば??演算子でいけますが、だがObjective-Cと同じことができないのがなんかうざい。
??演算子の後ろにすぐ実行するUITableViewCellを戻り値とするクロージャ書いたらなんかできそうな気がするも、邪道な感じがして試したくもない。

とりあえず外のスコープの変数用意しておいて、オプショナルバインディグが正攻法かなと思う。



2018年8月21日火曜日

UILabelのtextAlignment、justifiedについて

NSTextAlignmentには左寄せ(left)、右寄せ(right)、中央揃え(center)とあり、この3つはわかりやすいのですが、他の2つ(justifiedとnatural)がよくわからなく調べました。

naturalはiOSデバイスに設定されているロケールによって右寄せ、左寄せが変わるもの。昔の日本も文字を右から読んでましたね、国によっては右から読む国もあります。

 justifiedは日本語だとあまり関係がないため、使用する機会がありませんでしたが説明する機会が発生したため試してみました。

英文は左寄せすると右側に空白が発生し見た目がガクガクになりますが、justifiedを選ぶと適度に間隔を広げてくれて見た目がよくなります。
表示されている文字量に変化はありません。

長い英文として
こちらのサイトの桃太郎を使わせていただいています。
http://www.geocities.co.jp/HeartLand-Gaien/7211/

戻すと左寄せに、JustiΦでjustifiedになります。
どうしても555を思い出す。

2018年6月18日月曜日

Swift3,Swift4で乗算のループ

Swift3以上?Swift4でObjective-Cで書いたfor文1000まで10倍の乗算ループを書こうとしたら
for( int i=1; i<1000; i*=10 ) {
    NSLog(@"Hello %d",i);
}
予想以上に面倒で困った、詳細は不明だが、こうかけば期待通りに動いた
参照先https://code-examples.net/ja/q/2636c3a
// 乗算ループの書き方
let num = 1000
for i in sequence(first: 1, next: { $0 * 10 }).prefix(while: { num/$0 > 0 }) {
    print(i)
}
while文が残っていて本当によかったと感じる、Swift4以降でもうちょっと簡単な構文を期待したい。
var i = 1

while( i <= 1000 ) {
    print(i)
    i *= 10
}

2016年3月4日金曜日

(iOS)コンテナビューコントローラーの扱い

コンテナビューコントローラは、代表的なものとしてナビゲーションコントローラーとタブバーコントローラーがあるが、この2つを組み合わせたインターフェスを作った場合の制限事項

appleのドキュメントにはタブビューコントローラーからナビゲーションコントローラーの説明はあるが、その逆がない。

tab -> navi -> viewcontroller1 -> viewcontroller2
|-> navi -> viewcontroller3 -> viewcontroller4

という構成は普通。

nav -> tab-> viewcontroller1 -> viewcontroller2
            |->  viewcontroller3 -> viewcontroller4

こういう構成は説明がない。

Storyboardで組んだ場合、 タブビューコントローラー以下のビューコントローラにはナビゲーションバーがつくが、コントロールできなくなる。

正しい構成としては

nav -> tab(modal) -> viewcontroller1 -> viewcontroller2
            |->  viewcontroller3 -> viewcontroller4

ナビゲーションコントローラからタブビューコントローラーを出す時にモーダルビューとして出す。
すると一度ビューコントローラ階層がリセットされるので、おかしくはならないがナビゲーションバーは消滅する。

ナビゲーションバーは面倒だが自分で設置して、とりあえず体裁は整った。