Swift

Swiftやるぞ 1日目

 

まずApple IDを取得する。

→持ってる。

Xcodeをインストールする

→入れたぞ。

 

Swiftの型

  • Int型
    整数型
  • UInt型
    符号なし整数。普通はInt型を利用する
  • Float型
    実数型。小数点を含むものに利用します、有効桁数7桁
  • Double型
    実数型。小数点を含むものに利用します、有効桁数16桁
  • String型
    文字列型
  • Bool型
    真偽値を扱う。

 

シミュレータを起動してHello World

 

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // (1) ラベルに文字を入れる
        outputLabel.text = "Hello Swift!"
    }


    
    @IBOutlet weak var outputLabel: UILabel!
}

→できたぞ。

 

じゃんけんアプリつくるぞ!

じゃんけん画像の素材
https://drive.google.com/file/d/1OfAkCAU47v1DZ5gPxjh-V35DH3eWN2e9/view

 

Control + パーツをソースコードにドラッグアンドドロップで関連づけができる。

 

//
//  ViewController.swift
//  MyJanken
//
//  Created by 金広優 on 2020/02/14.
//  Copyright © 2020 Swift-Beginners. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBOutlet weak var answerImageView: UIImageView!
    
    @IBOutlet weak var answerLabel: UILabel!
    
    // じゃんけん (数字)
    var answerNumber = 0
    
    @IBAction func shuffleAction(_ sender: Any) {
        if answerNumber == 0 {
            answerLabel.text = "グー "
            answerImageView.image = UIImage(named: "gu")
        } else if answerNumber == 1 {
            answerLabel.text = "チョキ "
            answerImageView.image = UIImage(named: "choki")
        } else if answerNumber == 2 {
            answerLabel.text = "パー "
            answerImageView.image = UIImage(named: "pa")
        }
        
        // 次のじゃんけんへ
        answerNumber = answerNumber + 1

    }
}

 

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBOutlet weak var answerImageView: UIImageView!
    
    @IBOutlet weak var answerLabel: UILabel!
    
    // じゃんけん (数字)
    var answerNumber = 0
    
    @IBAction func shuffleAction(_ sender: Any) {
        
        answerNumber = Int.random(in: 0..<3)
        
        if answerNumber == 0 {
            answerLabel.text = "グー "
            answerImageView.image = UIImage(named: "gu")
        } else if answerNumber == 1 {
            answerLabel.text = "チョキ "
            answerImageView.image = UIImage(named: "choki")
        } else if answerNumber == 2 {
            answerLabel.text = "パー "
            answerImageView.image = UIImage(named: "pa")
        }
    }
}

 

 

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBOutlet weak var answerImageView: UIImageView!
    
    @IBOutlet weak var answerLabel: UILabel!
    
    // じゃんけん (数字)
    var answerNumber = 0
    
    @IBAction func shuffleAction(_ sender: Any) {
        
        var newAnserNumber = 0
        
        repeat {
            newAnserNumber = Int.random(in: 0..<3)
        } while answerNumber == newAnserNumber
        
        answerNumber = newAnserNumber
        
        if answerNumber == 0 {
            answerLabel.text = "グー "
            answerImageView.image = UIImage(named: "gu")
        } else if answerNumber == 1 {
            answerLabel.text = "チョキ "
            answerImageView.image = UIImage(named: "choki")
        } else if answerNumber == 2 {
            answerLabel.text = "パー "
            answerImageView.image = UIImage(named: "pa")
        }
    }
}

 

アイコンについて

1枚の画像から複数のアイコンを設定してくれるMakeAppIconというツールを利用する。

 

 

音楽アプリをつくろう

 

SimulatorはCommand + 矢印キーで横にしたり、回転できる。

 

音源のサンプルをドラッグアンドドロップでセットする。

 

AVFoundationを読み込む

 

 

import UIKit
import AVFoundation

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    // シンバルの音源ファイルを指定
    let cymbalPath = Bundle.main.bundleURL.appendingPathComponent("cymbal.mp3")
    
    // シンバル用ぷのプレイヤーインスタンスを作成
    var cymbalPlayer = AVAudioPlayer()

    @IBAction func cymbal(_ sender: Any) {
    }
}

 

 

 

import UIKit
import AVFoundation

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    // シンバルの音源ファイルを指定
    let cymbalPath = Bundle.main.bundleURL.appendingPathComponent("cymbal.mp3")
    // シンバル用のインスタンス作成
    var cymbalPlayer = AVAudioPlayer()

    @IBAction func cymbal(_ sender: Any) {
        do {
            // シンバル用のプレイヤーに、音源ファイル名を指定
            cymbalPlayer = try AVAudioPlayer(contentsOf: cymbalPath, fileTypeHint: nil)
            // シンバルの音源再生
            cymbalPlayer.play()
        } catch {
            print("🐱シンバルでエラーが発生したにゃん!")
        }
    }
    
    // シンバルの音源ファイルを指定
    let guitarPath = Bundle.main.bundleURL.appendingPathComponent("guitar.mp3")
    // シンバル用のインスタンス作成
    var guitarPlayer = AVAudioPlayer()
    
    @IBAction func guitar(_ sender: Any) {
        do {
            // ギター用のプレイヤーに、音源ファイル名を指定
            guitarPlayer = try AVAudioPlayer(contentsOf: guitarPath, fileTypeHint: nil)
            guitarPlayer.play()
        } catch {
            print("🐱ギターでエラーが発生したにゃん!")
        }
    }
    
    // BGMの音源ファイルを指定
    let backmusicPath = Bundle.main.bundleURL.appendingPathComponent("backmusic.mp3")
    // BGM用のインスタンス作成
    var backmusicPlayer = AVAudioPlayer()
    
    @IBAction func play(_ sender: Any) {
        do {
            // BGM用のプレイヤーに、音源ファイル名を指定
            backmusicPlayer = try AVAudioPlayer(contentsOf: backmusicPath, fileTypeHint: nil)
            backmusicPlayer.numberOfLoops = -1 // リピート設定
            backmusicPlayer.play()
        } catch {
            print("🐱BGMでエラーが発生したにゃん!")
        }
    }
    
    // Stopボタン
    @IBAction func stop(_ sender: Any) {
        // BGM停止
        backmusicPlayer.stop()
    }
}

 

リファクタリング

 

共通処理のsoundPlayer()を定義する

    fileprivate func soundPlayer(player:inout AVAudioPlayer, path: URL, count: Int) {
        do {
            player = try AVAudioPlayer(contentsOf: path, fileTypeHint: nil)
            player.numberOfLoops = count
            player.play()
        } catch {
            print("エラーが発生したにゃん🐱")
        }
    }

 

共通関数で置き換える。

import UIKit
import AVFoundation

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
    
    // シンバルの音源ファイルを指定
    let cymbalPath = Bundle.main.bundleURL.appendingPathComponent("cymbal.mp3")
    // シンバル用のインスタンス作成
    var cymbalPlayer = AVAudioPlayer()

    @IBAction func cymbal(_ sender: Any) {
        soundPlayer(player: &cymbalPlayer ,path:cymbalPath, count: 0)
    }
    
    // シンバルの音源ファイルを指定
    let guitarPath = Bundle.main.bundleURL.appendingPathComponent("guitar.mp3")
    // シンバル用のインスタンス作成
    var guitarPlayer = AVAudioPlayer()
    
    @IBAction func guitar(_ sender: Any) {
        soundPlayer(player: &guitarPlayer ,path:guitarPath, count: 0)
    }
    
    // BGMの音源ファイルを指定
    let backmusicPath = Bundle.main.bundleURL.appendingPathComponent("backmusic.mp3")
    // BGM用のインスタンス作成
    var backmusicPlayer = AVAudioPlayer()
    
    @IBAction func play(_ sender: Any) {
        soundPlayer(player: &backmusicPlayer ,path:backmusicPath, count: -1)
    }
    
    // Stopボタン
    @IBAction func stop(_ sender: Any) {
        // BGM停止
        backmusicPlayer.stop()
    }
    
    fileprivate func soundPlayer(player:inout AVAudioPlayer, path: URL, count: Int) {
        do {
            player = try AVAudioPlayer(contentsOf: path, fileTypeHint: nil)
            player.numberOfLoops = count
            player.play()
        } catch {
            print("エラーが発生したにゃん🐱")
        }
    }
}

 

アクセス修飾子

  • public
    どこからでもアクセス可能
  • internal
    同じモジュール内のみアクセス可能
  • fileprivate
    ファイル内のみアクセス可能
  • private
    定義内の中でのみアクセス可能

 

地図アプリをつくる

 

Text Fieldを貼り付ける

Return KeyにSearchを設定

 

mapで検索してMap Kit Viewを選択する

 

 

Text FieldのConstraintを設定

Map kit Viewも同様に設定します。

 

Assistantを設定

 

 

Controlボタンを押しながらドラッグアンドドロップをします。

 

ConnectionをOutletに設定してConnect

 

Connectionの種別

  • Outlet … そのUI部品をどこかで参照したい時
  • Action … そのUI部品の動作を決めたい時

 

 

 

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBOutlet weak var inputText: UITextField! // ←● 追加された
}

 

Map kit Viewも同様に設定します。

 

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBOutlet weak var inputText: UITextField!
    
    @IBOutlet weak var dispMap: MKMapView!
}

 

MapKitをimport

import UIKit
import MapKit // ←● 追加

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBOutlet weak var inputText: UITextField!
    
    @IBOutlet weak var dispMap: MKMapView!
}

 

import UIKit
import MapKit

class ViewController: UIViewController, UITextFieldDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // Text Fieldのdelegate通知先を設定
        inputText.delegate = self
    }

    @IBOutlet weak var inputText: UITextField!
    @IBOutlet weak var dispMap: MKMapView!
    

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // キーボードを閉じる
        textField.resignFirstResponder()
        
        // 入力された文字を取り出す(2)
        if let searchKey = textField.text {
            // 入力された文字をデバッグエリアに表示(3)
            print(searchKey)
        }
        
        return true
    }
}

viewDidLoad()は画面が描画された時に最初に実行されるメソッド。

 

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // キーボードを閉じる(1)
        textField.resignFirstResponder()
        
        // 入力された文字を取り出す(2)
        if let searchKey = textField.text {
            // 入力された文字をデバッグエリアに表示(3)
            print(searchKey)
        }
        // デフォルトで動作を行うのでtrueを返す(4)
        return true
    }

 

 

検索を押したらキーボード閉じればOK

 

このコードあるから入力後にキーボードが閉じられる。

textField.resignFirstResponder()

 

textFieldShouldReturn()は予め規定されているdelegateメソッド。

 

 

 

Xcodeを日本語化していないことに気づく

 

緯度経度を取得して表示

import UIKit
import MapKit

class ViewController: UIViewController, UITextFieldDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // Text Fieldのdelegate通知先を設定
        inputText.delegate = self
    }

    @IBOutlet weak var inputText: UITextField!
    @IBOutlet weak var dispMap: MKMapView!
    

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // キーボードを閉じる(1)
        textField.resignFirstResponder()
        
        // 入力された文字を取り出す(2)
        if let searchKey = textField.text {
            // 入力された文字をデバッグエリアに表示(3)
            print(searchKey)
            
            // CLGeocoderインスタンスを取得(5)
            let geocoder = CLGeocoder()
            
            // 入力された文字から位置情報を取得
            geocoder.geocodeAddressString(searchKey, completionHandler: { (placemarks, error) in
                
                // 位置情報が存在する場合は、unwrapPlacemarksに取り出す(7)
                if let unwrapPlacemarks = placemarks {
                    // 1件目の情報を取り出す(8)
                    if let firstPlacemark = unwrapPlacemarks.first {
                        // 位置情報を取り出す(9)
                        if let location = firstPlacemark.location {
                            // 位置情報から緯度経度をtargetCordinateに取り出す(10)
                            let targetCoordinate = location.coordinate
                            
                            // 緯度経度をデバッグエリアに表示(11)
                            print(targetCoordinate)
                        }
                    }
                }
            })
        }
        // デフォルトで動作を行うのでtrueを返す(4)
        return true
    }
}

 

住所などの文字列から位置情報を取得するメソッド

geocoder.geocodeAddressString(searchKey, completionHandler: { (placemarks, error) in
    // 以下略
})

クロージャが利用されていて、位置情報が取得できたタイミングで{}内が動きます。

 

 

 

import UIKit
import MapKit

class ViewController: UIViewController, UITextFieldDelegate {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
        // Text Fieldのdelegate通知先を設定
        inputText.delegate = self
    }

    @IBOutlet weak var inputText: UITextField!
    @IBOutlet weak var dispMap: MKMapView!
    

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // キーボードを閉じる(1)
        textField.resignFirstResponder()
        
        // 入力された文字を取り出す(2)
        if let searchKey = textField.text {
            // 入力された文字をデバッグエリアに表示(3)
            print(searchKey)
            
            // CLGeocoderインスタンスを取得(5)
            let geocoder = CLGeocoder()
            
            // 入力された文字から位置情報を取得(6)
            geocoder.geocodeAddressString(searchKey, completionHandler: { (placemarks, error) in
                
                // 位置情報が存在する場合は、unwrapPlacemarksに取り出す(7)
                if let unwrapPlacemarks = placemarks {
                    // 1件目の情報を取り出す(8)
                    if let firstPlacemark = unwrapPlacemarks.first {
                        // 位置情報を取り出す(9)
                        if let location = firstPlacemark.location {
                            // 位置情報から緯度経度をtargetCordinateに取り出す(10)
                            let targetCoordinate = location.coordinate
                            
                            // 緯度経度をデバッグエリアに表示(11)
                            print(targetCoordinate)
                            
                            // ピンを生成(12)
                            let pin = MKPointAnnotation()
                            
                            // ピンの置く場所に緯度経度を設定(13)
                            pin.coordinate = targetCoordinate
                            
                            // ピンのタイトルを設定(14)
                            pin.title = searchKey
                            
                            // ピンを地図を置く(15)
                            self.dispMap.addAnnotation(pin)

                            // 緯度経度を中心にして半径500mの範囲を表示(16)
                            self.dispMap.region = MKCoordinateRegion(center: targetCoordinate, latitudinalMeters: 500.0, longitudinalMeters: 500.0)
                        }
                    }
                }
            })
        }
        // デフォルトで動作を行うのでtrueを返す(4)
        return true
    }
}

 

アンラップ

 

if let 変数名 = ターゲット

if let searchKey = textField.text {

}

textField.textの値がsearchKey変数に代入できたら … 値があるなら {}を実行

 

 

delegate

  1. クラスで行いたい処理の一部を他のクラスに任せる
  2. 任せた処理を指定したクラスに通知

仲介する仕組み🐱✨

登場するもの

  • ①処理を依頼するクラス
    ViewController
    ・UITextFieldクラスから作ったインスタンスのinputTextに対して、「inputText.delegate = self」と記述してdelegateの通知先を自分自身と設定。
    ・通知したい内容はtextFieldShoudReturnメソッドを指定している
  • ②依頼する、依頼されるクラスを仲介するプロトコル
    UITextFieldDelegate
    検索キーワードが入力されてReturn(Search)が押された時の情報を取得して、通知先がViewControllerであることをUITextFieldに教える
  • ③処理を依頼されるクラス
    UITextField
    ・UITextFieldDelegateから通知を受けたら、UITextFieldは、View Controllerに「return」がタップされた時の情報を教える

 

 

マップの種別を切り替え

 

Buttonを選択してドラッグアンドドロップ

 

ButtonのTypeをDetail Disciosureに設定

 

Constraintを右端になるように設定

 

Actionを指定してConnect

・・・
        }
        // デフォルトで動作を行うのでtrueを返す(4)
        return true
    }
    
    
    @IBAction func changeMapButton(_ sender: Any) {
    }
}

 

トグルボタンにする

        // デフォルトで動作を行うのでtrueを返す(4)
        return true
    }
    
    
    @IBAction func changeMapButton(_ sender: Any) {
        // mapTypeプロパティ一値をトグル
        // 標準 → 航空写真 → 航空写真+標準
        // 3D Flyover → 3D Flyover+標準
        // → 交通機関
        if dispMap.mapType == .standard {
            dispMap.mapType = .satellite
        } else if dispMap.mapType == .satellite {
            dispMap.mapType = .hybrid
        } else if dispMap.mapType == .hybrid {
            dispMap.mapType = .satelliteFlyover
        } else if dispMap.mapType == .satelliteFlyover {
            dispMap.mapType = .hybridFlyover
        } else if dispMap.mapType == .hybridFlyover {
            dispMap.mapType = .mutedStandard
        } else {
            dispMap.mapType = .standard
        }
    }

 

 

 

 

 

Amazonおすすめ

iPad 9世代 2021年最新作

iPad 9世代出たから買い替え。安いぞ!🐱 初めてならiPad。Kindleを外で見るならiPad mini。ほとんどの人には通常のiPadをおすすめします><

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)