storyboardを使わずに姓名診断アプリを作る

ドットインストールの以下のレッスン

dotinstall.com

を、storyboardを使わずにswiftのみで作ってみる。

storyboardを使わないプロジェクト作成

これ参照

画面に必要な部品

姓名診断画面

f:id:gawao:20150330002724j:plain

診断結果画面

f:id:gawao:20150330002756j:plain

NavigationControllerを設置してタイトルを表示

参考

012 UINavigationControllerの表示 - Swift Docs

コード

AppDelegate.swift 抜粋

var window: UIWindow?
var myNavigaionController: UINavigationController?

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: bject]?) -> Bool {

    // ViewControllerを生成
    let myFirstViewController: ViewController = ViewController()
    // Navigation Controllerを生成
    myNavigaionController = UINavigationController(rootViewController: myFirstViewController)
    
    self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
    self.window?.backgroundColor = UIColor.whiteColor()
    // Navigation ControllerをrootViewControllerに設定
    self.window?.rootViewController = myFirstViewController
    self.window?.makeKeyAndVisible()
    
    return true
}

ViewController.swift(姓名診断画面) 抜粋

override func viewDidLoad() {
    super.viewDidLoad()

    // タイトルを設定する
   self.title = "姓名診断"
}

実行結果

f:id:gawao:20150330002913j:plain

ViewControllerの追加と部品の配置

参考

コード

ViewController.swift(姓名診断画面)

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    let sendButton: UIButton = UIButton()
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Controllerのタイトルを設定する
        self.title = "姓名診断"
    
        // UITextFieldを作成する
        let name: UITextField = UITextField(frame: CGRectMake(0, 0, 300, 30))
        // 最初に表示する文字を設定
        name.text = "名前を入力"
        // Delegateを設定する
        name.delegate = self
        // 枠を表示する
        name.borderStyle = UITextBorderStyle.RoundedRect
        // UITextFieldの表示する位置を設定
//        name.layer.position = CGPoint(x: self.view.frame.width/2, y: 150)
        name.layer.position = CGPoint(x: 160, y: 150)
        // Viwに追加する
        self.view.addSubview(name)
        
        // 送信ボタンを設定する
        sendButton.frame = CGRectMake(0, 0, 50, 40)
        // 背景色を設定する
        sendButton.backgroundColor = UIColor.lightGrayColor()
        sendButton.showsTouchWhenHighlighted = true
        // 枠を丸くする
        sendButton.layer.masksToBounds = true
        // タイトルを設定する
        sendButton.setTitle("Send", forState: UIControlState.Normal)
        sendButton.setTitleColor(UIColor.blackColor(), forState: UIControlState.Normal)
        // コーナーの半径を設定する
        sendButton.layer.cornerRadius = 10.0
        // ボタンの位置を指定する
        sendButton.layer.position = CGPoint(x: 340, y: 150)
        // タグを設定する
        sendButton.tag = 1
        // イベントを追加する
        sendButton.addTarget(self, action: "showResult:", forControlEvents: .TouchUpInside)
        // ボタンをViewに追加する
        self.view.addSubview(sendButton)

    }

    /*
        ボタンイベント
    */
    func showResult(sender: UIButton) {
        // 移動先のViewを定義する
        let resultViewController = ResultViewController()
        // ResultViewに移動する
        self.navigationController?.pushViewController(resultViewController, animated: true)
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

ResultViewController(診断結果画面)

import UIKit

class ResultViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Controllerのタイトルを設定
        self.title = "診断結果"
        
        // Labelを作成
        let label: UILabel = UILabel(frame: CGRectMake(0, 0, 200, 40))
        // 背景色を付ける
        label.backgroundColor = UIColor.lightGrayColor()
        // 文字を代入
        label.text = "あなたの点数は…"
        // テキストを中央寄せにする
        label.textAlignment = NSTextAlignment.Center
        // ラベルを配置する座標を設定する
        label.layer.position = CGPoint(x: self.view.bounds.width / 2, y: 200)
        // ViewにLabelを追加
        self.view.addSubview(label)
        
        // 診断結果表示Labelを作成
        let resultLabel: UILabel = UILabel(frame: CGRectMake(0, 0, 200, 80))
        // 枠線を付ける
        resultLabel.layer.borderColor = UIColor.redColor().CGColor
        // 枠線の太さ
        resultLabel.layer.borderWidth = 2.0
        // 文字を代入
        resultLabel.text = "100点"
        // テキストを中央寄せ
        resultLabel.textAlignment = NSTextAlignment.Center
        // フォントサイズを大きくして太字に
        resultLabel.font = UIFont.boldSystemFontOfSize(64)
        // ラベルを配置する座標を設定する
        resultLabel.layer.position = CGPoint(x: self.view.bounds.width / 2, y: 300)
        // ViewにLabelを追加
        self.view.addSubview(resultLabel    )
        
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

実行結果

f:id:gawao:20150330003218j:plain f:id:gawao:20150330003235j:plain


ここまでで、

  • Sendボタンをクリックして診断結果画面に遷移
  • 診断結果画面から姓名診断画面に遷移

は出来た

姓名診断のText Fieldで入力した値のチェック・値を診断結果画面に表示・点数を表示

参考

010 UIAlertControllerでアラートを表示 - Swift Docs


ここではまってしまった。。。
segueを使わないで画面間で値を受け渡すやり方がわからずに2時間くらい悩んでいた。
名前受け渡し用の変数を作り、そこに値をセットするようにしたら出来たが、これでいいのか・・

コード

ViewController.swift(姓名診断画面)

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    let sendButton: UIButton = UIButton()
    var nameField: UITextField!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        // Controllerのタイトルを設定する
        self.title = "姓名診断"
    
        // UITextFieldを作成する
        nameField = UITextField(frame: CGRectMake(0, 0, 300, 30))
        // 最初に表示する文字を設定
        nameField.placeholder = "名前を入力"
        // Delegateを設定する
        nameField.delegate = self
        // 枠を表示する
        nameField.borderStyle = UITextBorderStyle.RoundedRect
        // UITextFieldの表示する位置を設定
        nameField.layer.position = CGPoint(x: 160, y: 150)
        // Viwに追加する
        self.view.addSubview(nameField)
        
        // 送信ボタンを設定する
        sendButton.frame = CGRectMake(0, 0, 50, 40)
        // 背景色を設定する
        sendButton.backgroundColor = UIColor.lightGrayColor()
        sendButton.showsTouchWhenHighlighted = true
        // 枠を丸くする
        sendButton.layer.masksToBounds = true
        // タイトルを設定する
        sendButton.setTitle("Send", forState: .Normal)
        sendButton.setTitleColor(UIColor.blackColor(), forState: .Normal)
        // コーナーの半径を設定する
        sendButton.layer.cornerRadius = 10.0
        // ボタンの位置を指定する
        sendButton.layer.position = CGPoint(x: 340, y: 150)
        // タグを設定する
        sendButton.tag = 1
        // イベントを追加する
        sendButton.addTarget(self, action: "showResult:", forControlEvents: .TouchUpInside)
        // ボタンをViewに追加する
        self.view.addSubview(sendButton)

    }

    /*
        ボタンイベント
    */
    func showResult(sender: UIButton) {
        // 空文字チェック
        if nameField.text == "" {
            showAlert()
        } else {
            // 移動先のViewを定義する
            let resultViewController = ResultViewController()
            // ResultViewに移動する
            self.navigationController?.pushViewController(resultViewController, animated: true)
            
            // TODO これで渡せるな・・?
            resultViewController.myName = nameField.text
        }
    }
    /*
        エラーアラートを表示
    */
    func showAlert() {
        // UIAlertControllerを作成する
        let myAlert = UIAlertController(title: "エラー", message: "診断したい名前を入力してください", preferredStyle: .Alert)
        // OKのアクションを作成する
        let myOkAction = UIAlertAction(title: "OK", style: .Default, handler: nil)
        // OKのアクションを追加する
        myAlert.addAction(myOkAction)
        // UIAlertを発動する
        presentViewController(myAlert, animated: true, completion: nil)
        
    }
    
    /*
    改行ボタンが押された際に呼ばれる
    */
    func textFieldShouldReturn(textField: UITextField) -> Bool {
        
        // returnを押すとキーボードが隠れる
        textField.resignFirstResponder()
        
        // sendButtonと同じ処理を
        sendButton.sendActionsForControlEvents(.TouchUpInside)
        return true
    }
    
    /*
        UITextFieldが編集された直後に呼ばれる
    */
    func textFieldDidBeginEditing(textField: UITextField) {
        println("textFieldDidBeginEditing: \(textField.text)")
    }
    
    /*
        UITextFieldが編集終了する直前に呼ばれる
    */
    func textFieldShouldEndEditing(textField: UITextField) -> Bool {
        println("textFieldShouldEndEditing: \(textField.text)")
        return true
    }
    
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

ResultViewController(診断結果画面)

import UIKit

class ResultViewController: UIViewController {
    
    // 入力された名前を入れる
    var myName: String = ""
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Controllerのタイトルを設定
        self.title = "診断結果"
        
        // Labelを作成
        let label: UILabel = UILabel(frame: CGRectMake(0, 0, 200, 40))
        // 背景色を付ける
        label.backgroundColor = UIColor.lightGrayColor()
        // 名前を代入
        label.text = "\(myName)の点数は…"
        // テキストを中央寄せにする
        label.textAlignment = NSTextAlignment.Center
        // ラベルを配置する座標を設定する
        label.layer.position = CGPoint(x: self.view.bounds.width / 2, y: 200)
        // ViewにLabelを追加
        self.view.addSubview(label)
        
        // 診断結果表示Labelを作成
        let resultLabel: UILabel = UILabel(frame: CGRectMake(0, 0, 200, 80))
        // 枠線を付ける
        resultLabel.layer.borderColor = UIColor.redColor().CGColor
        // 枠線の太さ
        resultLabel.layer.borderWidth = 2.0
        // 点数を表示
        let score = arc4random_uniform(101)
        resultLabel.text = "\(score)点"
        // テキストを中央寄せ
        resultLabel.textAlignment = NSTextAlignment.Center
        // フォントサイズを大きくして太字に
        resultLabel.font = UIFont.boldSystemFontOfSize(64)
        // ラベルを配置する座標を設定する
        resultLabel.layer.position = CGPoint(x: self.view.bounds.width / 2, y: 300)
        // ViewにLabelを追加
        self.view.addSubview(resultLabel)
        
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }
}

f:id:gawao:20150330003821j:plain f:id:gawao:20150330003833j:plain


ここまでで大体機能は出来たので、細かいところを変更

修正点

結果画面から姓名診断画面に戻った時に名前が入ったままなので消す

姓名診断画面を表示した時にテキストフィールドにフォーカスをセットする

参考

UITextField、UITextViewのフォーカス制御 - iOSアプリ開発トピック

ViewController.swift(姓名診断画面)

    /*
        Viewが表示される直前に行う処理
    */
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        // 名前入力テキストフィールドを空にする
        nameField.text = ""
        // 名前入力テキストフィールドにフォーカスする
        nameField.becomeFirstResponder()
    }

キーボートのreturnSendに変える

参考

UITextField/UITextViewの文字入力で覚えておくと便利なこと

ViewController.swift(姓名診断画面)

override func viewDidLoad() {
// 〜省略〜
        // キーボードのReturnキーをSendに変える
        nameField.returnKeyType = UIReturnKeyType.Send
        // Viwに追加する
        self.view.addSubview(nameField)
// 〜省略〜
}

結果画面を表示したときに姓名診断画面の「テキストフィールドとボタン」が少しの間表示されているので消す

こんなやつ

f:id:gawao:20150330004040g:plain

ResultViewController(診断結果画面)

    /*
    Viewが表示される直前に行う処理
    */
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        // TODO viewの背景色を設定
        // これで前の画面の残像(テキストフィールドとボタン)は消えたけど・・・??
        self.view.backgroundColor = UIColor.whiteColor()
    }

f:id:gawao:20150330004114g:plain

残像が消えたようだけどこれでいいのか・・・??

完成

画面

f:id:gawao:20150330004147g:plain

コード

iOSで姓名診断アプリを作る swift版


やりたいことは出来ましたが、何だかスッキリしない(>_<)