読者です 読者をやめる 読者になる 読者になる

webプログラマがiosアプリ開発を始めて学んだことまとめ

swift objective-c iphone

はじめに

今までwebアプリの開発をほぼphpでおこなってきたのですが、ここ2ヶ月iosアプリ開発をして学んだことをまとめます。
社内に経験者がいないため基本独学で進めて、たまに知人に質問というか相談をしてるかんじです。
とくに最初の1ケ月はけっこうとまどったのでなぜとまどったのかもまとめてゆければと思います

すべてコードで書く

最初の1か月は、入門書を読んだりして基本的なことを勉強したのですが実案件でちょっと複雑なレイアウトとか出てくるとすぐつまづきました。で、知人のアドバイスでiPhoneアプリ開発の場合、規模が大きくなればなるほどすべてコードで実装して管理してることもあるということを聞いてあれこれ悩まず、すべてコードで実装する方針に変えたところスムーズに開発が進みました。

storyboardとxibファイルでのUIの実装も慣れてる人がやったら便利なのだろうとは思いますが、これの使い方調べてたらなかなか進まず結局原始的ではあるのかもしれませんが、すべてコードで実装するとういことにしました。コードだと修正した内容なども一目瞭然なので今のところ違和感なしです。

過去にjavaアプレット開発の勉強したことがあったのですが、そんなイメージで1つずつボタンとかをつくって画面に貼り付けていくようなそんなイメージの実装ですね、、、地味な作業なのですが

ちなみに超有名かとは思いますが、自分は以下のサイトをかなり参考にさせていただいています
https://sites.google.com/a/gclue.jp/swift-docs/

Autolayoutは考えない

すべてコードで実装すると決めた時点でとりあえずAutolyaoutのことは忘れることにしました。
まだ案件の途中なので、これから問題も発生するのかもしれないのですがとりあえず今のところ問題にならずに作業できています。

ボタンやラベルなど、それぞれx座標、y座標、幅、高さを指定して貼り付けていくやり方です。
熟練の方からしたら非効率なのでしょうが、初心者の自分にはあってました。
これは自分仕様なのですが、以下のような感じでフォーマットてきなことなものを決めて機械的に画面を作成しています

画面作成のコード@swift ※ラベルとボタンを横並びに並べる場合

// margin
var marginHorizon = 5
var marginVertical = 5

// 最大値
var widthMax = self.frame.width
var heightMax = self.frame.height

// widthをきめる
var widthLabel: CGFloat = 100
var widthButton: CGFloat = 100

// heightをきめる
var heightLabel: CGFloat = 44
var heightButton: CGFloat = heightLabel

// x位置をきめる
var xLabel: CGFloat = marginHorizon
var xButton: CGFloat = marginHorizon + widthLabel + marginHorizon

// y位置をきめる
var yLabel: CGFloat = marginVertical
var yButton: CGFloat = yLabel

// ラベルを追加
var label: UILabel = UILabel()
label.frame = CGRectMake(xLabel, yLabel, widthLabel, heightLabel)
label.text = "ラベル"
self.view. addSubview(label)

// ボタンを追加
var button: UIButton = UIButton()
button.frame = CGRectMake(xButton, yButton, widthButton, heightButton)
button.setTitle("ボタン", forState: UIControlState.Normal)
self.view. addSubview(xButton , yButton, widthButton, heightButton)

UITableViewを駆使する(というか強引に使ってみる)

HTMLでいえば、テーブルレイアウトでwebページを作るイメージでしょうか。
UIScrollViewとかもあるのですが、自分には難しかったです、、、

たとえば縦長の画面がある場合にUIViewControllerのviewに、順次addSubviewしていった場合で
1画面におさまらなくなった場合に、勝手に縦方向にスクロールしてくれるものと思っていたのですがそんなことはなく、画面が切れてしまいます。
HTMLだったらありえないのに、、、やっぱりぜんぜん違うのだなと

で、僕の場合はこういう画面は問答無用でUITableViewを使うことにしています。
理由は他のやりかたがよくわからないからなのですが、、、

たとえば画面の上部にラベルやらボタンやらがたくさんあって、その下から画面の下までリストが並んでるページの場合
UITableViewのヘッダーにラベルやボタンをおいて、リストの部分はテーブルのセルを使うといった感じになります。
かなり強引だと思ったのですが、けっこうこういう形で実装している人は多いみたいなのでよしとしました。

参考にならない可能性高いですが、自分のフォーマットは以下になります

class SampleViewController: UIViewController, UITableViewDelegate, UITableViewDataSource
{
    var tableView: UITableView! // テーブルビュー
    var tableData: ["データ1", "データ2", ・・・] // データ

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // テーブルビュー準備
        tableView = UITableView(frame: CGRect(x:0, y:0, width:self.view.frame.width, height:self.view.frame.height))
        tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "UITableViewCell")

        tableView.delegate = self
        tableView.dataSource = self
        self.view.addSubview(tableView)
    }

    // テーブルセルの高さをかえします
    func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
        return 60
    }

    // テーブルセルにデータをセットします
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("UITableViewCell", forIndexPath: indexPath) as! UITableViewCell
        cell.setData(self.tableData[indexPath.row], isLayout: true)
        return cell
    }
    
    // テーブルの行数をかえします
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.tableData.count
    }
    
    // テーブルヘッダーの高さをかえします(フッターだけどヘッダーとして利用)
    func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        let heightView = self.setHeaderView(tableView,isLayout: false) as! CGFloat
        return heightView
    }
    
    // テーブルヘッダーにViewをセットしてかえします(フッターだけどヘッダーとして利用)
    func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let viewHeader = self.setHeaderView(tableView, isLayout: true) as! UIView
        return viewHeader
    }

    // Viewの追加とViewの高さを求めてかえします
    func setHeaderView(tableView: UITableView, isLayout: Bool) -> AnyObject {

        // ベースとなるView(高さは変わるので暫定)
        let viewHeader = UIView()
        viewHeader.frame = CGRectMake(0, 0, tableView.frame.width, 300)
        viewHeader.backgroundColor = UIColor.whiteColor()

        // ラベルやボタンなどの幅、高さ、x座標、y座標をそれぞれ求めて作成します
        // 省略・・・
        
        if isLayout == true {
            viewHeader.addSubview(searchBar)
            return viewHeader
        } else {
            return heightView
        }
    }
}

テーブルヘッダーでなくフッターを使ったのは、テーブルヘッダーはスクロールすると画面に残ってしまうので僕はこんなかんじで実装することにしています。調べたらヘッダーがついてこないやりかたもあったのですが、僕はこんなかっこ悪い実装をしています(自分的には直感的で。わかりやすいため)

UITableViewを駆使する2

if indexPath.row == 0 {
    // 1行目の場合
} else if indexPath.row == 1 {
    // 2行目の場合
} else if indexPath.row == 2 {
    // 3行目の場合
} else {
    // その他の場合
}

UITableViewを多様していると上記のように行ごとの処理をハードコードする場面が出てくることもあると思います。
本当はよくないのかもしれませんが、こんな感じでやるものだと割り切ってしまうとあれこれ悩まずに開発が進む場合もありました

1画面 = UIViewControllerということを理解する

これも玄人の方からしたら違うのかもしれませんが、初心者はあれこれ悩まずとりあえずこう解釈しておくと開発が進むと思います。
たとえば、「一覧画面」「新規登録画面」「詳細画面」の3つのの画面をもつメモアプリを作るとしたら、まずは
ListViewContoller、NewViewController、DetailViewControllerなどの3つのUIVIewControllerを継承したクラスを作るものだと考えます。
で、ラベルやボタンなどを置いて、とりあえずページ遷移だけするアプリを作るところから始めるのが良いと思います

ネットで色々調べていると、UIViewControllerをaddSubviewしているUIViewControllerとか難しい話もよく出てきますが初心者がこういうこととか考えると混乱するので難しいことは考えないよう方が良いと思います。
画面の一部を共通化する場合は、UIViewControllerでなくUIViewを共通化してゆきます

UINavigationControllerとUITabBarControllerをなんとなく理解する

どちらも複数のUIViewControllerを管理するクラスです。たしかコンテナViewControllerと呼んでいたような。
うまく説明できないのですが
・ボタンなどをおすとページ遷移する画面(UINavigationController)
・画面下部に固定されたタブをもつ画面(UITabBarController)
をのような画面をつくる場合はこれらを使うことになると思うので、キーワードとして覚えておくと良いと思われます

storyboardとxibファイルの使い所

使わないと書きましたが実際は、storyboardは軽く使っています。
レイアウトなどを作る用途では使っていないのですが、画面遷移などを表現するのには使っています

xibファイルについても今回は使っていないのですが、レイアウトが固定のページでは使ったほうが断然早くなるかもとちょっと思っています、、、
ただ画面によっては、条件によってラベルを表示したりしなかったりとかあると思います。そういう動的なものがある画面はコードが必要になってくるので、1からコードで作ったほうがいいのかなとか思います。
最初に入門書とか読んだときに「画面作成はstoryboardとxibで全部やるもの」と思い込んでしまったのがよくなかったわけでした、、、
・レイアウトが静的な画面・・・GUI使う
・レイアウトが動的な画面・・・GUI使わない

cocoapods

ライブラリを管理するツールで、これは業務でも使うことが多いようなので使います

まとめ

なにも考えずにすべてコードで書くと工夫しないとコードが見ずらくなっていくとは思います。
が、とりあえず動くものを作るのが先決でその後に問題の箇所を自分なりに整理して行ければと思います

以上です