swiftのイニシャライザまわりでコンパイルエラーになることが多かったのでいろいろ試してみた
swiftのイニシャライザまわりでコンパイルエラーになることが多くてちょっと調べてみた。
いろいろ実験しているが本当は原理を知らないといけないと思う。
でもうんこエンジニアなので原理を理解できない
§ まとめ
最初にまとめを書いておく
定数の定義 → super.init() → メソッドを呼ぶ
の順番で呼ぶと良い
§ 実験
継承してないパターン
■ initからメソッド呼び出し
これは普通に通る
import Foundation class SampleUseCase { init() { bind() } func bind() { print("bind") } }
■ let で変数を設定した場合
let の変数が全部初期化されたあとはメソッドを呼べる
=>これは問題なく通る
■ let変数の前にメソッドをcall
Use of 'self' in method call 'bind' before all stored properties are initialized
「全てのプロパティーが初期化される前にメソッドをcallするときはselfを使え」とのこと
■ selfをつけてみる
=>selfをつけても結果は同じ。。?
継承しているパターン
■ 継承してサブクラスにした場合
=> 先にsuper.init を呼べとのこと
■ メソッドを呼ぶ前にsuper.initを呼ぶ。
=> これはOK
■ let定数の前にsuper.initをよんでみた。
=> これはダメとのこと
■ メソッドよびだしの後にsuper.initを呼んでみた
=> ダメ
iOS テーブルのセルがタブにめり込む問題
下記の画像のようにテーブルビューの一番下のセルがタブにめり込んで出てこないのはなんでだろうと思って調べました。
次の3つのパラメーターの設定方法に問題があったみたい。
■ isTranslucentの設定
Translucent は 半透明とのこと。
ナビバーやタブバーに設定するもので背景を半透明に透過するかを指定する。
navigationController?.navigationBar.isTranslucent = false // ナビバーを半透明にしない tabBarController?.tabBar.isTranslucent = false // タブバーを半透明にしない
■ extendedLayoutIncludesOpaqueBars の設定
extended Layout Includes OpaqueBars 拡張 レイアウト 含める 不透明な部分
不透明な部分を拡張レイアウトに含めるかどうか
extendedLayoutIncludesOpaqueBars = true
の場合はナビバーやタブバーを半透明にしなかった場合にもナビバー、タブバーの部分を拡張レイアウトに含める。
■ edgesForExtendedLayout の設定
edges For Extended Layout 端っこ のための 拡張 レイアウト
どこを拡張レイアウト用の端とするか。
edgesForExtendedLayout = .all
つまり
- タブバーを半透明にしないで、
- 不透明な部分も拡張レイアウトに含めて、
- 拡張レイアウトを下端にも適用させる。
といった設定になっている場合にタブの下にセルがめり込んで最後のセルが出てこないといった問題が発生する。
問題の発生するコードを掲載します。
// // SampleViewController.swift // import UIKit class SampleViewController: UIViewController { let sampleDatas = ["1","2","3","4","5","6","7","8","9","0","1","2","3","4","5","6","7","8","9","0"] override func viewDidLoad() { super.viewDidLoad() title = "タブ1" // 1. ナビバー、タブバーを半透明にするかの設定 navigationController?.navigationBar.isTranslucent = false tabBarController?.tabBar.isTranslucent = false // 2. 半透明ではない部分も拡張レイアウトに含めるかの設定 extendedLayoutIncludesOpaqueBars = true // 3. どの部分が拡張レイアウトの対象となるか edgesForExtendedLayout = .bottom let tableView = UITableView() tableView.dataSource = self tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell") view.addSubview(tableView) tableView.translatesAutoresizingMaskIntoConstraints = false tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true } } extension SampleViewController: UITableViewDataSource { public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return sampleDatas.count } public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) cell.textLabel?.text = sampleDatas[indexPath.row] if indexPath.row % 2 == 0 { cell.backgroundColor = UIColor(red: 0.5, green: 0.5, blue: 1, alpha: 1) } else { cell.backgroundColor = UIColor(red: 0.5, green: 1, blue: 0.5, alpha: 1) } return cell } }
IMP型について調べてみる
IMP型について調べてみようかと思います。
とりあえずよくわからなかったので実装してみます。
ARCだとちょっと工夫が必要とのことでMRCで実装します。
ExampleObject.h
#import <Foundation/Foundation.h> @interface ExampleObject : NSObject -(void)exec; @end
ExampleObject.m
#import "ExampleObject.h" #import <objc/Object.h> @interface SampleClass : NSObject -(void)sampleMethod; @end @implementation SampleClass -(void)sampleMethod { NSLog(@"sampleMethodが実行されたー"); } @end @implementation ExampleObject -(void)exec { id obj = [SampleClass new]; SEL method = @selector(sampleMethod); IMP func = [obj methodForSelector:method]; func(); } @end
これを下記の通り実行すると
ExampleObject *exampleObject = [[ExampleObject alloc] init]; [exampleObject exec];
実行結果は
2015-03-22 15:50:40.383 Example[24294:641518] sampleMethodが実行されたー
となります