ラベル Swift3 の投稿を表示しています。 すべての投稿を表示
ラベル Swift3 の投稿を表示しています。 すべての投稿を表示

2018年4月8日日曜日

音楽再生アプリを作ってみた

音楽を再生するためだけのシンプルなアプリを作ってみました。
Swift勉強がてらなのでクソ設計ですが、誰かの参考になればと思い、GitHubにて公開しております。
MITライセンスです。
[GitHub] Nokokinoko/nusic

質問などあればお気軽にどうぞ!

2018年4月4日水曜日

モーダル範囲外のタッチを判定

タッチした際にモーダル等の矩形の範囲内外を判定する方法です。
  • Xcode 8.3.3
  • Swift 3.1
import UIKit

class ExampleViewController: UIViewController {
  private var _Dismiss: Bool = false
  private let TAG: Int = 100

  override func viewDidLoad() {
    super.viewDidLoad()

    self.view.backgroundColor = UIColor.gray
    _Dismiss = false

    let viewAdd = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 400))
    viewAdd.backgroundColor = UIColor.white
    viewAdd.center = self.view.center
    viewAdd.tag = TAG
    self.view.addSubview(viewAdd)
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }

  override func touchesBegan(_ touches: Set<uitouch>, with event: UIEvent?) {
    if _Dismiss {
      return
    }

    let point = touches.first?.location(in: self.view)
    let viewAdd: UIView = self.view.viewWithTag(TAG)! as UIView

    if !viewAdd.frame.contains(point!) {
      _Dismiss = true
      // 範囲外をタッチした時の処理
    }
  }
}

touchesBeganなので指が画面に触れた時のイベントです。
touchesEndedにすれば指が画面から離れた時のイベントになります。
ただ、touchesBeganに画面制御を記述すると反応の早い、ユーザビリティの高いアプリとユーザに判断されます。まぁこれも使い所次第ですが😅
課金とかにtouchesBeganで処理されたら私は速攻アプリアンインストールします😅
なんか信用出来ないですからね…

というかUIがボタンならBeganでselectな制御(グレースケールしたりとか縮小させたりとか)して、Movedで範囲内外を判定、Endedで範囲内(というかBeganで触ったものと同一のままならとか)ならselectedな制御して範囲外なら何もしない(タッチ状態フラグを解除程度)みたいな制御が普通ですね。

こういう制御例ってあまりネットに載らないですよね😇
各社ノウハウとして溜まってるだけで。
まぁ気が向いたらその辺も公開していきます🙌掲載するコード量がとんでもないことになりそう😇

2018年4月3日火曜日

遷移時にブラーを自然に重ねて表示

ブラー効果を簡単に利用するではSwiftの利用方法を紹介しました。
ただこれを使って重ねて表示(Over Current Context)するとフェードインした後、急にブラーの背景に変わって違和感があります。
今回はブラー効果を重ねて表示する際に自然に表示出来るよう調整する方法です。
  • Xcode 8.3.3
  • Swift 3.1
import UIKit

class ExampleViewController: UIViewController {
  private var _Blur: UIVisualEffectView!

  override func viewDidLoad() {
    super.viewDidLoad()

    _Blur = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.dark))
    _Blur.frame = self.view.frame
    _Blur.alpha = 0.0
    self.view.addSubview(_Blur)
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }

  override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    UIView.animate(
      withDuration: 0.25,
      animations: { self._Blur.alpha = 1.0 }
    )
  }
}

なんか無理矢理感が否めないです🙇
ブラーをいじったり、アニメーションスタイルをいじれば良いのですが、私はそこまでのめり込むつもりがないのです😇

2018年4月2日月曜日

ブラー効果を簡単に利用する

iOSにて開発時に用意されているブラー効果(いわゆるすりガラスのようなぼかし効果です)をSwiftで簡単に利用する方法です。
  • Xcode 8.3.3
  • Swift 3.1
では早速コードになります。
let _Blur = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.dark))
_Blur.frame = self.view.frame
self.view.addSubview(_Blur)

この例ではUIBlurEffectStyle.darkを指定しているため黒のブラーです。
他にも.lightで白ブラー、.extraLightでlightよりも薄い白のブラーとなります。

ぼかし具合とか変えたい場合は結構いじる必要がありそうです😇
なんか実際に奥側に当たる箇所にブラー効果を加えてるのではなく、内部でスクリーンショット撮ってブラー効果を加えたものを設置してるのかな?
深く理解していませんが、そこまでApple様に加担するつもりはありませんので黙って用意されたもので我慢しておきます😇

2018年4月1日日曜日

TabBar + Navigation構成でViewに遷移

TabBarにNavigationではタブ要素にナビを追加して親子関係を作りました。
TabBarからViewに遷移ではタブのアイテムにViewへ遷移するための処理を追加しました。
今回はタブ要素にナビを追加した上で表示されたViewから別Viewへ遷移するための処理を紹介します。
  • Xcode 8.3.3
  • Swift 3.1
別Viewへ遷移するためのトリガーはボタンタッチとかでも良いですし、TableViewのCellタッチでも何でも良いです。
適切な所に処理を記述して下さい。
TabBarからViewに遷移と同様、重ねて表示(Over Current Context)します。
let vcNext = UIViewController()
vcNext.modalPresentationStyle = .overCurrentContext
parent?.parent?.present(vcNext, animated: false, completion: nil)

構成としてTabBarがアイテム要素を管理、各アイテムはNavigationであり、表示するViewControllerを持っています。
別Viewへ遷移するためのトリガーはこのViewControllerとなりますので、2つ上のparentにpresentを実行します。

なんかもう少しスマートなやり方がありそうな気がします…
相対的な指定が汎用性だったり拡張性を失わせておる😈

2018年3月31日土曜日

TabBarからViewに遷移

前回TabBarにNavigationという記事を書きました。
  • Xcode 8.3.3
  • Swift 3.1
今回はこれに加えてタブのアイテムにタブ表示に依存しないViewを追加したいと思います。
モーダルも以下コードで再現出来るので参考にして頂ければと。
import UIKit

class TabViewController: UITabBarController, UITabBarControllerDelegate {
 
 class DummyViewController: UIViewController {}

 private var _Example1: UINavigationController!
 private var _Example2: UINavigationController!
 private var _Example3: UINavigationController!
 private var _Modal: DummyViewController!
 
 override func viewDidLoad() {
  super.viewDidLoad()
  
  self.view.backgroundColor = UIColor.white
  
  _Example1 = UINavigationController(rootViewController: Example1ViewController())
  _Example2 = UINavigationController(rootViewController: Example2ViewController())
  _Example3 = UINavigationController(rootViewController: Example3ViewController())
  _Modal = DummyViewController()
  
  _Example1.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.featured, tag: 1)
  _Example2.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.featured, tag: 2)
  _Example3.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.featured, tag: 3)
  _Modal.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.featured, tag: 4)
  
  self.setViewControllers([_Example1!, _Example2!, _Example3!, _Modal!], animated: false)
  self.delegate = self
 }
 
 override func didReceiveMemoryWarning() {
  super.didReceiveMemoryWarning()
 }

 func tabBarController(_ tabBarController: UITabBarController, shouldSelect viewController: UIViewController) -> Bool {
  if viewController is DummyViewController {
   let example = ExampleViewController()
   example.modalPresentationStyle = .overCurrentContext
   self.present(example, animated: false, completion: nil)
   return false
  }
  return true
 }
}

これで_Modalに該当するアイテムをタップした時だけタブ内ではなく、ExampleViewControllerを重ねて表示します。

ExampleViewControllerの背景を黒透過にして白いレイヤを表示するよう制御すれば、モーダルを再現出来るかと🙆

2018年3月30日金曜日

TabBarにNavigation

以前StoryBoardを使わずにUITabBarControllerStoryBoardを使わずにUINavigationControllerという記事を書きました。
  • Xcode 8.3.3
  • Swift 3.1
今回はUITabBarControllerにNavigationを追加したいと思います。
もちろんStoryBoardは使いません。
全然関係ないですが、これを実現しようとGoogle先生に聞くとStoryBoardやらSegueやらばかりがHITします😇
あれって使ってる人いるんですね😇

親View

import UIKit

class TabViewController: UITabBarController {
 
 private var _Example1: UINavigationController!
 private var _Example2: UINavigationController!
 private var _Example3: UINavigationController!
 
 override func viewDidLoad() {
  super.viewDidLoad()
  
  self.view.backgroundColor = UIColor.white
  
  _Example1 = UINavigationController(rootViewController: Example1ViewController())
  _Example2 = UINavigationController(rootViewController: Example2ViewController())
  _Example3 = UINavigationController(rootViewController: Example3ViewController())
  
  _Example1.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.featured, tag: 1)
  _Example2.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.featured, tag: 2)
  _Example3.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.featured, tag: 3)
  
  self.setViewControllers([_Example1!, _Example2!, _Example3!], animated: false)
 }
 
 override func didReceiveMemoryWarning() {
  super.didReceiveMemoryWarning()
 }
}


子となるView

import UIKit

class Example1ViewController: UIViewController {
 override func viewDidLoad() {
  super.viewDidLoad()
  
  self.navigationItem.title = "Example1"
  
  self.navigationItem.leftBarButtonItem = nil
  
  let btnRight = UIBarButtonItem(title: "Next >", style: UIBarButtonItemStyle.plain, target: self, action: #selector(Example1ViewController.goNext))
  self.navigationItem.rightBarButtonItem = btnRight
 }
 
 override func didReceiveMemoryWarning() {
  super.didReceiveMemoryWarning()
 }
 
 @objc func goNext() {
  self.navigationController?.pushViewController(Example1NextViewController(), animated: true)
 }
}


子ViewからNavigationで遷移するView

StoryBoardを使わずにUINavigationControllerという記事ではExample2ViewControllerでした(紛らわしくてすいません🙇)
import UIKit

class Example1NextViewController: UIViewController {
 override func viewDidLoad() {
  super.viewDidLoad()
  
  self.navigationItem.title = "Example1Next"
  
  let btnLeft = UIBarButtonItem(title: "< Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(Example1NextViewController.goBack))
  self.navigationItem.leftBarButtonItem = btnLeft
  
  self.navigationItem.rightBarButtonItem = nil
 }
 
 override func didReceiveMemoryWarning() {
  super.didReceiveMemoryWarning()
 }
 
 @objc func goBack() {
  self.navigationController?.popViewController(animated: true)
 }
}


Example2, 3についても同じように実装すればタブで切替えながらナビからも操作出来るようになります!
自分のコードから抽出して掲載しているので動かない等あればお気軽にどうぞ!

2018年3月29日木曜日

セクション設定したTableView

以前Xibを利用してTableViewを実装する方法を紹介しました。
Xibを使ってTableViewのCellを登録・その1
Xibを使ってTableViewのCellを登録・その2
  • Xcode 8.3.3
  • Swift 3.1
今回はこのテーブルにセクションを設定したいと思います。
コードは同じのを使い回します🙇
元コードを再掲。行数3のテーブルを表示するだけのViewControllerです😀
import UIKit

class ParentViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
  override func viewDidLoad() {
    super.viewDidLoad()

    _TableView = UITableView()
    _TableView?.frame = self.view.frame
    _TableView?.register(UINib(nibName: "ExampleTableViewCell", bundle: nil), forCellReuseIdentifier: "ExampleIdentifier")
    _TableView?.delegate = self
    _TableView?.dataSource = self
    self.view.addSubview(_TableView)
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }

  // データ数
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 3
  }

  // セルデータを返す
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "ExampleIdentifier", for: indexPath)
    switch indexPath.row {
      case 1:
        cell.textLabel?.text = "1行目"
      case 2:
        cell.textLabel?.text = "2行目"
      case 3:
        cell.textLabel?.text = "3行目"
      default: break
    }
    return cell
  }

  // セル選択
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    // セル選択時の処理
  }
}


ではここにセクションを2つ追加してみます。
一応分かりやすいようにセクション1は行数3、セクション2は行数4として設定します。
セクション設定とセクション毎のデータ設定を把握してもらえればと😀
import UIKit

class ParentViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
  override func viewDidLoad() {
    super.viewDidLoad()

    _TableView = UITableView()
    _TableView?.frame = self.view.frame
    _TableView?.register(UINib(nibName: "ExampleTableViewCell", bundle: nil), forCellReuseIdentifier: "ExampleIdentifier")
    _TableView?.delegate = self
    _TableView?.dataSource = self
    self.view.addSubview(_TableView)
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }

  // セクション数
  func numberOfSections(in tableView: UITableView) -> Int {
    return 2
  }

  // セクション名
  func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
    if section == 1 {
      return "セクション1だよ"
    }
    else if section == 2 {
      return "セクション2になります!"
    }
    return nil
  }

  // セクション単位のデータ数
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if section == 1 {
      return 3
    }
    else if section == 2 {
      return 4
    }
    return 0
  }

  // セルデータを返す
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "ExampleIdentifier", for: indexPath)

    if indexPath.section == 1 {
      switch indexPath.row {
        case 1:
          cell.textLabel?.text = "セクション1の1行目"
        case 2:
          cell.textLabel?.text = "セクション1の2行目"
        case 3:
          cell.textLabel?.text = "セクション1の3行目"
        default: break
      }
    }
    else if indexPath.section == 2 {
      switch indexPath.row {
        case 1:
          cell.textLabel?.text = "セクション2の1行目"
        case 2:
          cell.textLabel?.text = "セクション2の2行目"
        case 3:
          cell.textLabel?.text = "セクション2の3行目"
        case 4:
          cell.textLabel?.text = "セクション2の4行目"
        default: break
      }
    }

    return cell
  }

  // セル選択
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    // セル選択時の処理
  }
}


通常こんなハードコーディングすることはありません。
JSON等を解析して配列にしたりして利用することとなると思います。
データ数を返すメソッドをcount使ったりすると思うので、適宜改善して頂ければと!

2018年3月28日水曜日

StoryBoardを使わずにUINavigationController

以前ブログにも書きましたがStoryBoardを使わずに開発をしており、今回はUINavigationControllerを実装していきます。
  • Xcode 8.3.3
  • Swift 3.1
これもUITableViewController同様、難しいことはないです。
ある程度Xcode側で用意されてるので、それを利用するだけなので😅
ただし細かい調整したい場合は元クラスを調べる等、調査が必要ですので適宜Jump to definitionしましょう🙆

動作としてExample1のナビの右上NextをタップするとExample2へ遷移。
Example2ではナビの左上BackをタップでExample1へ戻れるようにします。
import UIKit

class Example1ViewController: UIViewController {
 override func viewDidLoad() {
  super.viewDidLoad()
  
  self.navigationItem.title = "Example1"
  
  self.navigationItem.leftBarButtonItem = nil
  
  let btnRight = UIBarButtonItem(title: "Next >", style: UIBarButtonItemStyle.plain, target: self, action: #selector(Example1ViewController.goNext))
  self.navigationItem.rightBarButtonItem = btnRight
 }
 
 override func didReceiveMemoryWarning() {
  super.didReceiveMemoryWarning()
 }
 
 @objc func goNext() {
  self.navigationController?.pushViewController(Example2ViewController(), animated: true)
 }
}</textarea><br />
<br />
<textarea class="code">import UIKit

class Example2ViewController: UIViewController {
 override func viewDidLoad() {
  super.viewDidLoad()
  
  self.navigationItem.title = "Example2"
  
  let btnLeft = UIBarButtonItem(title: "< Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(Example2ViewController.goBack))
  self.navigationItem.leftBarButtonItem = btnLeft
  
  self.navigationItem.rightBarButtonItem = nil
 }
 
 override func didReceiveMemoryWarning() {
  super.didReceiveMemoryWarning()
 }
 
 @objc func goBack() {
  self.navigationController?.popViewController(animated: true)
 }
}

使わないleftBarButtonItemやrightBarButtonItemをnilしなくても設定しなければ何も表示されませんが、今後の事も考えると初期化(あえて非表示してますよアピール)しておきましょう。
また、通常こんなハードコーディングをすることはありません。
例としてあえてnil設定を記述したのは、条件によってnilしたりアイテム設定したりというのが書きやすいようにです😀
abstractみたい(Swiftではprotocol extensionか?)にして他メソッドで設定するのも良いですし🙌

最後にこのViewControllerを呼出しましょう。
let example1 = UINavigationController(rootViewController: Example1ViewController())
self.present(example1, animated: true, completion: nil)

我、アクセス権を要求す

SwiftにてMediaPlayer関連の処理を実装している際、以下のようなエラーが👊
[access] This app has crashed because it attempted to access privacy-sensitive data without a usage description. 
The app's Info.plist must contain an NSAppleMusicUsageDescription key with a string value explaining to the user how the app uses this data.

毎回載せてるので一応環境も。
  • Xcode 8.3.3
  • Swift 3.1
まぁ意味は読んだままなんですが、ユーザのプライバシー情報見ようとしてるな?使用目的をInfo.plistに書けよな!とのこと🙇
天下のApple様、敵いませんわ。

ということでInfo.plistを開いて+ボタンを押して追加しましょう。
キー名にPrivacy - XXXというのがあるのでコードに応じて使用目的をValueに書きましょう。これがそのままアプリが該当の情報を見ようとした時にアラートとして表示されます。
調べた情報を見ると、Valueが空文字でも起動可、XcodeのValidateも可、らしいですが、アプリ申請時にリジェクトされるそうです。
なのでやましい理由があるわけでもないので、素直に書いておきましょう。

また、このアラートの文言を多言語対応したい場合、Info.plistにはデフォルト言語にて記述。
他の言語についてはおなじみのInfoPlist.stringsにて多言語対応しましょう!
InfoPlist.stringsについては一応この記事を参考に。
[iOS] アプリ名を国ごと変更したい場合

Baseにはデフォルト言語を記述し、Japanaseには日本語にて記述します。
ここはシステム的な文言になるので、ふざけない方が良い気がします(例えば最高の時間を提供しますとかクールなサウンドを楽しみますとか…書いてて寒いですが😅)
[ Base ]
"NSAppleMusicUsageDescription" = "Play Music";

[ Japanese ]
"NSAppleMusicUsageDescription" = "音楽を再生します";

最後にInfo.plist上のキー名と内部のキー名、簡単な説明の一覧を下記しておきます!ご参考までに🙌
  • Privacy - Bluetooth Peripheral Usage Description
    • NSBluetoothPeripheralUsageDescription
    • Blootooth
  • Privacy - Calendars Usage Description
    • NSCalendarsUsageDescription
    • カレンダー
  • Privacy - Camera Usage Description
    • NSCameraUsageDescription
    • カメラ
  • Privacy - Contacts Usage Description
    • NSContactsUsageDescription
    • 連絡先
  • Privacy - Health Share Usage Description
    • NSHealthShareUsageDescription
    • ヘルス
  • Privacy - Health Update Usage Description
    • NSHealthUpdateUsageDescription
    • ヘルスの更新
  • Privacy - HomeKit Usage Description
    • NSHomeKitUsageDescription
    • ホームキット
  • Privacy - Location Always Usage Description
    • NSLocationAlwaysUsageDescription
    • 位置情報 (常に許可)
  • Privacy - Location When In Use Usage Description
    • NSLocationWhenInUseUsageDescription
    • 位置情報 (使用中のみ許可)
  • Privacy - Microphone Usage Description
    • NSMicrophoneUsageDescription
    • マイク
  • Privacy - Motion Usage Description
    • NSMotionUsageDescription
    • 加速度センサ
  • Privacy - Music Usage Description
    • NSAppleMusicUsageDescription
    • ミュージック
  • Privacy - Photo Library Usage Description
    • NSPhotoLibraryUsageDescription
    • 写真ライブラリ
  • Privacy - Reminders Usage Description
    • NSRemindersUsageDescription
    • リマインダー
  • Privacy - Siri Usage Description
    • NSSiriUsageDescription
    • Siri
  • Privacy - Speech Recognition Usage Description
    • NSSpeechRecognitionUsageDescription
    • 音声認識

2018年3月27日火曜日

StoryBoardを使わずにUITabBarController

以前ブログにも書きましたがStoryBoardを使わずに開発をしており、今回はUITabBarControllerを実装していきます。
  • Xcode 8.3.3
  • Swift 3.1
タブに3つのアイテムを持ったTabBarControllerを作ります。
まぁそこまで難しいコードでもないです。Google先生に聞けばすぐ出てきます😅
import UIKit

class TabViewController: UITabBarController {
 
 private var _Example1: UIViewController!
 private var _Example2: UIViewController!
 private var _Example3: UIViewController!
 
 override func viewDidLoad() {
  super.viewDidLoad()
  
  self.view.backgroundColor = UIColor.white
  
  _Example1 = UIViewController()
  _Example2 = UIViewController()
  _Example3 = UIViewController()
  
  _Example1.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.featured, tag: 1)
  _Example2.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.featured, tag: 2)
  _Example3.tabBarItem = UITabBarItem(tabBarSystemItem: UITabBarSystemItem.featured, tag: 3)
  
  self.setViewControllers([_Example1!, _Example2!, _Example3!], animated: false)
 }
 
 override func didReceiveMemoryWarning() {
  super.didReceiveMemoryWarning()
 }
}

タブのアイテム画像は全部featuredですが、実行すればTabBarControllerが確認出来ると思います!

2018年3月26日月曜日

だから嫌いなんだ

Swiftで開発中に以下のようなエラーに見舞われました。
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[UIViewController _loadViewFromNibNamed:bundle:] loaded the XXX nib but the view outlet was not set.'
  • Xcode 8.3.3
  • Swift 3.1
ファイル構成とやりたいことは下記。
PlayViewController.swift
PlayView.swift
PlayView.xib

PlayViewController内でPlayViewを生成する。
PlayViewはUIViewを継承していて、xibファイルを元にレイアウト。
これでPlayViewを使用する前に一度実行してみたら、先のエラーが発生しました😇

意味が分からなすぎて発狂するところでしたが、救いの手が🙏
ViewControllerが自動で読むxibファイルに注意

  • XXXViewControllerクラスはXXXViewController.xibを読み込もうとする
  • 読み込めなければ、Controllerを除いたファイルを読み込もうとする(XXXView.xib)
先のような構成だとPlayViewControllerはPlayViewController.xibを読み込もうとするが、用意していないので、次にPlayView.xibを読み込もうとする。
PlayView.xibはたしかにあるのだが、PlayViewで使用されることを想定しているのでエラー。こういうことでした😇
これってXcode側で制御出来ないのかな…まぁApple様の高尚な考えがあるのでしょう。

サイト様の例にもありますが、PlayContentViewなどにリネームするのが良さそうですね🙆

Xibを使ってTableViewのCellを登録・その2

前回の記事でxibファイルの作成を説明しました。
今回は実際にコードから登録&呼出しについて。
  • Xcode 8.3.3
  • Swift 3.1

せっかくならdelegate

TableViewを持つViewControllerを定義します。
import UIKit

class ParentViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
  override func viewDidLoad() {
    super.viewDidLoad()

    _TableView = UITableView()
    _TableView?.frame = self.view.frame
    _TableView?.register(UINib(nibName: "ExampleTableViewCell", bundle: nil), forCellReuseIdentifier: "ExampleIdentifier")
    _TableView?.delegate = self
    _TableView?.dataSource = self
    self.view.addSubview(_TableView)
  }

  override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
  }

  // データ数
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 3
  }

  // セルデータを返す
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "ExampleIdentifier", for: indexPath)
    switch indexPath.row {
      case 1:
        cell.textLabel?.text = "1行目"
      case 2:
        cell.textLabel?.text = "2行目"
      case 3:
        cell.textLabel?.text = "3行目"
      default: break
    }
    return cell
  }

  // セル選択
  func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    // セル選択時の処理
  }
}

本来セクション等も合わせて説明したいですが、とりあえず今回は3行のテーブルを表示する処理に限定します。

UITableViewDelegateUITableViewDataSourceを継承し、コード内のメソッドを実装してください(実装しないとエラーになります)

9行目の処理にてTableViewにregisterメソッドにて登録しています
nibNameには前回作成したファイル名を指定します。
後から指定するためのforCellReuseIdentifierも一緒に登録しており、こちらは定数で定義するかメソッドから取得するようにしましょう(今回は簡素にするため直接指定しています)
その辺のプログラマとしての常識はいちいち書くのも面倒なので適宜読み替えて下さい。

26行目の処理にて登録してあるCellを呼出しています。
指定したIDをwithIdentifierに渡してください。

これでxibファイルのレイアウトで3行のTableViewが生成されるはずです!
簡単ではありますが以上になります。質問などあればお気軽にどうぞ!

2018年3月25日日曜日

Xibを使ってTableViewのCellを登録・その1

前回の記事でStoryBoardを使わずにアプリ開発をする方法を書きました。
しかしStoryBoardを使うメリットの一つとしてUIを直感的に設置出来るという点があります。
今回はTableViewのCellをXibでデザインして、それをコードから呼出して設定する方法を紹介します。
今回はひとまずxibファイルを作る所まで!
  • Xcode 8.3.3
  • Swift 3.1

てかXibって何?

その前にXibとはXML Interface Builderの略らしいです。

コード内ではNibという名称で出てきます。
これはNextstep Interface Builderの略です。Nextstepの時点でお気付きだと思いますが、Apple様のいつものやつです。
こちらはバイナリファイルとなっており、XibもビルドするとNibに変換されるとかなんとか…

StoryBoardも結局Xibの集合体とも呼べると思います。
まぁその辺は私も深く理解はしていません。というかコードを実行する上では必要のない知識なのでUIを作る上で.xibというファイルを作って、コード上ではNibという名前で指定すれば動作する程度の認識で良いかと。

ゲーム開発フレームワーク作りたいとかpsdファイルから画面設計したいとかなら必須知識ですけどね😇
そんな修羅の道歩みたくないです😇

まずはXibファイルを作成

XcodeにてNew FileしてCocoa Touch Classを作成
Also create XIB fileにチェック
SubclassにUITableViewCellを指定
(名前は適当にExampleTableViewCellとしておきます)

するとExampleTableViewCell.swift, ExampleTableViewCell.xibが出来ると思います。
swiftファイルを確認すると確かにUITableViewCellを継承していることを確認出来るかと思います。
class ExampleTableViewCell: UITableViewCell {
    override func awakeFromNib() {
        super.awakeFromNib()
        // Initialization code
    }

    override func setSelected(_ selected: Bool, animated: Bool) {
        super.setSelected(selected, animated: animated)

        // Configure the view for the selected state
    }
}

swiftファイルは今回はいじることはないのでそっ閉じでOKです🙆

xibファイルをクリックするとStoryBoardで見たような直感的(笑)の画面になるかと思います。
まず問題ないと思いますがCustom ClassがExampleTableViewCellになっていることを確認して下さい。
であとは好きにデザインして下さい。StyleやSelectionの項目をいじるなり、Labelを追加するなり😀

次の記事でコードからXibを利用する方法について書きます。
記事書くのも疲れる🙇

2018年3月24日土曜日

StoryBoardを使わない

最近cocos2d-xとUnityでアプリ制作をしており、ふとSwiftって使ったことがないなぁと思いました🙌
スマートフォンのネイティブってLobi連携のためのAndroidJavaとかSNSサービス連携であったりブラウザ起動だったりをObject-Cで組んだり、局所的な部分でしか扱ったことがなく、一度しっかりSwiftのみでアプリを作ってみたいなと。
  • Xcode 8.3.3
  • Swift 3.1
ということでXcodeにてCreate a new Xcode projectしてみたのです。
で、おなじみのProduct NameだったりOrganization Identifierを設定して、LanguageをSwiftにしていざCreate

すると見慣れぬMain.storyboardとLaunchScreen.storyboardというものが…
結論から言うと個人的にはこのStoryBoardは何も使えないと判断しました😇
例えるならNintendoLabo的なことしか出来ない。
アプリの性質によってはそれで十分てことはあるだろうし、非エンジニアにも扱えるって利点はあるのかもしれないですが、エンジニアもしくは今後もアプリを作っていくのであればStoryBoardは使わないのを推奨します。

ということでまずはMain.storyboardを削除します。
そしてInfo.plistのMain storyboard file base nameも削除します。
AppDelegate.swiftを開き、applicationメソッドを以下のように修正します。
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
 self.window = UIWindow(frame: UIScreen.main.bounds)
 self.window?.rootViewController = ExampleViewController()
 self.window?.makeKeyAndVisible()
 
 return true
}

ちなみにLaunchScreen.storyboardやInfo.plist内のLaunch screen interface file base nameは残しておきましょう!
ここで画面サイズ等の情報を取得しているそうです。

でStoryBoardを使う利点であるUIの直感的な配置についてはXibを利用します。
それについては次の記事で書こうかと😀

2018年3月23日金曜日

Swiftのバージョンを調べる

Swiftのバージョンを調べる方法
ターミナルを起動しましょう。
ターミナル?なにそれ?って人はアプリケーション -> ユーティリティにあるので、そちらを起動

あとは以下コマンドを実行
swift --version

ターミナルはexitとかで終了させちゃってください