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が生成されるはずです!
簡単ではありますが以上になります。質問などあればお気軽にどうぞ!

Bloggerにソースコードを貼りたい

Bloggerにてソースコードを貼りたくてSyntaxHighlighterを使っていました。
ただ挙動がなんか好きではなくて乗り換えたくなり、ex-code-prettifyに変えたのです。
ちょっとだけ安心と信頼の純正Google code-prettifyも使ってみたのですが、何かが気に食わなくてすぐやめました(何が気に食わなかったのかは忘れました😅)

ex-code-prettifyを導入したが…

でもex-code-prettifyに変えたらHTTPとHTTPSが混在しとるよエラーが頻発😇
Chromeの検証で確認するとMixed Contentうんたらかんたら…

BloggerのHTML編集でhttp接続している箇所を洗い出したのですが、全て修正しても直らず😇
htmlタグの箇所にhttp記述のものが残ってましたが、それは変更してテーマを保存してもBlogger側に元に戻される。ここはユーザ操作で修正出来ない箇所なのかな…よく分からず。
そもそもMixed Contentとしてエラーになってる箇所とは別だし😈

で、ex-code-prettifyの情報を探してたら、製作者様のサイトを発見。
CYOKODOG様

記事執筆時点で最終変更履歴が2014年😇
あ、あれ…開発もうストップしてる???
いやぁ見た目とか挙動が好みだったため非常に残念です…

ということで他のプラグインを探しました。
正直こんなことに何時間もかけたくないので半分イライラしながら(笑)

最終結論

SyntaxHighlighterに戻しました。
導入事例が多いので…何か分からないことが起きた時にすぐGoogle先生に聞けば解決するのって大事🙏
既存記事を修正するのが超しんどかった😇

再導入にあたってはこちらの記事を参考にさせて頂きました!
Bloggerでソースコードを貼り付ける(改改)
分かりやすい&ご自身の設定例を載せてくれてたのですんなり導入出来ました!
ありがとうございます🙇

Bloggerやめて別ブログに乗り換えようと思ったぞぉジョジョーーー!!

祝!note投稿!

以前noteに登録する旨の記事を書きました。
そしてnoteに無事投稿が完了したことをお知らせします!

エンジニアよ、稼ぐか搾取されるか #1
エンジニアよ、稼ぐか搾取されるか #2

内容についてはフリーランスとしてのエンジニアの実情といいますか、フリーランスとして必要な土台といいますか…
私がエンジニアとはいえ、具体的にはソーシャルゲームになりますので、少し職場雰囲気的に明るいというかエンターテイメント性を大事にしているというかなので、少し雰囲気が異なる部分があるかもしれません。
同じ境遇の人に少しでも役立てばという思いで書いてみました!
感想などコメント頂けると嬉しいです😀😀😀

以上、2つの記事を投稿しました🙌

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を利用する方法について書きます。
記事書くのも疲れる🙇

Google先生…

Google先生で何か検索して、リンクをクリックした後にブラウザバックすると、クリックしたページの真下に「他の人はこちらも検索」ってのが最近出るようになったじゃないですか。
あれ、得してる人います?Google以外で😅

Googleがアレを積極的に出したいのは分かります。
色んなワードで検索してもらうことで広告料回収したいのですよね。

別に表示する分には構わないのです。
Googleだってボランティアじゃないのだから色々な方法で回収にかかるのは至極当然です🙌
でもブラウザバックした時にニュルンって出てくるんですよ😅

同じ感覚の人がいるか分からないのですが、私の場合、実装方法とか検索して調べる時に自分の疑問点と100%合致した答えってまず見つからないのですよ。
なので検索結果をクリックする際も他検索結果も見ながらクリックしていて、パッと見てあ、これじゃないってなったらすぐブラウザバックして他検索結果に移る訳です。
その時間、わずか数秒な訳です。

で、すぐ次検索結果の位置にマウスを合わせていてレンダリング完了次第クリックするのです。
それがニュルンタイムのせいでちょっと待ち時間が発生するんです😅
その時間、わずかコンマ数秒です。

でもそれがうっとうしい!
激しくうっとうしい!

ChromeにCSS拡張すれば消せるぽいですが、記事見る限り不安定そう…
【Google】「他の人はこちらも検索」の表示を無効化する方法についてメモ

他検索エンジン使う気にはなれないし、CSS拡張もやりたくない…
私はただGoogle先生を信じて待つのでした🙏

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を利用します。
それについては次の記事で書こうかと😀

のせのせ!鳥獣ギガンテスをリリース

のせのせ!鳥獣ギガンテスをリリースしました!
鳥獣戯画の著作権が切れたとのことで、こちらのキャラクタを活かしてスタックゲームを作りました。
どうぶつタワーバトルの便乗ですね😅

ただ、こちら普通にアプリ申請しても通りません!
先にも書いたようにどうぶつタワーバトルの模倣アプリが蔓延しているため、独自性がないという理由でApple様にリジェクトされます。

私の場合、それは事前に予想していたので少し独自性を持たせました。
他スタックゲーム(この呼び方が正しいのか分からないですが)は土台があって、そこに何個積めたかをスコア化しています。
鳥獣ギガンテスではスタックした後、全てのオブジェクトが静止していることを確認した後、不可視のバーを土台から計測して擬似的に積んだ高さをスコア化しています。
正直何個積めたかという管理はすごく簡単なんです。単純にインクリメントしていけばいいだけですから😅
不可視バーの制御や処理の軽量化には気を遣いました。

また、物理エンジンを利用したゲームも始めてだったので色々勉強になりました。
誰がどこまで管理するか(イベントドリヴンにするにあたり重要)、MVC設計に基いているか等、考慮する点は多いと思います。

オンライン対戦化したいけど、コスパが悪そうで躊躇してます😇

設計や物理エンジン等、ご質問があればお気軽にどうぞ!

2018年3月23日金曜日

Swiftのバージョンを調べる

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

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

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

そうだ、noteしよう

noteに登録してみました。
有料設定も出来るし、ブログのような使い方も出来ます。
ここにソーシャルゲーム運営のノウハウを投稿してみようかと。
投稿した際にはこちらにもお知らせ致します。

売上とかについてもある程度の期間を持って発表しようと思います!
とりあえず私のページを貼っておきます。
ヘッダ画像は安定のボブネミミッミ😅

ラーメン道をリリース

ラーメン道というアプリをリリースしました。
こちらはUnity ver 5.6で制作しております。
何気にUnityでアプリリリースってしたことなかったんですよね。なので勉強がてらXcodeプロジェクト書き出しからアプリ書き出しまでやってみたかったんです😀

ゲーム内容的には指定の注文通りに適切なゲージをタップで止めてこなしていく感じです。相変わらずさほど目立った機能はないです😅

ただ、タップの制御やUniRXを用いたイベントドリヴン設計など一度本格的に組み込んでみたかったので、勉強になりました。
アプリが面白いかどうかも重要ですが、アプリリリースを目標に勉強した感じですね。机上で勉強するだけじゃ得られないものもたくさんあるので。

あとタイトルシーンではアプリサムネイルにもいますが、Live2Dを組み込んでいます。
タッチした方向を向かせたり、キャラクタタップ時に音声を再生しています。
無料でサンプル配布しているヒヨリちゃん(?)だっけな。そんな感じの子を利用させてもらってます。
サンプルデータについてはこちらをご確認下さい!

Live2DのUnity組み込みやUniRXなどご質問あればお気軽にどうぞ!

2018年3月22日木曜日

クソWEBツールを作りました

アニメ、ポプテピピック内でボブネミミッミという前衛的なコーナーがあります。
なんか上手く説明出来ないですし、何が面白いとか自分でもよく分からないのですが、目を離せない魔力があります😅

ボブネミミッミはこんな感じ。
絵柄が本物のポプテピピックと違いすぎると思うと思いますが、それがボブネミミッミなのです。
意味とか考えてはいけないのです。

ある放送で「何気ないマンボがサンバ師匠をきずつけた」「何気ないオーレがフラメンコ師匠をきずつけた」といったワードが出てきます。
前後のやり取りがないと意味が分からないと思った方!大丈夫です、これがほぼそのままで、意味なんてないので😅
元ネタがあるっぽいですが、誰も得しないので言及しません。

本題なのですが、この「何気ない○○が○○をきずつけた」って汎用性の高いワードだと思ったわけです。
そこで作りました。その名もなにきずジェネレータ
○○に該当する部分を入力することで画像が生成されます😇

久しぶりにPHP触ったのですが、GDライブラリが使ってみたかったので…
文字数多すぎるとはみ出てしまいますし、そのままtwitter投稿出来れば良かったり等、改善点はたくさんあると思うのですが、突貫で作ったのでお許しを🙇
所要時間は2時間くらい。

twitter投稿機能作ろうとするとデベロッパ登録が必要で、面倒なんですよね…
一度登録しておいたら今後のツール制作も幅が広がるでしょうけど、面倒臭さが勝ちました🙌

和の色クイズと洋の色クイズをリリース

和の色クイズというクイズアプリをリリースしました。
小豆色や桜色など日本の繊細な色をクイズ形式で当てていくアプリとなります。
正解すると色情報をコレクションして、色コードも確認出来ます。

和の色クイズに反して洋の色クイズというアプリもリリースしております。
こちらはサーモンピンクやチョコレートなどの英語名の色をクイズ形式で当てていくアプリとなります。

どちらもアプリ開発のチュートリアルみたいなアプリです😅
強いて言うならクイズ情報をCSVで保持して正解済みか否かを判定してランダムにクイズ生成しているくらいかな…
いや、それもGoogle先生に聞けばすぐ教えてくれるような程度ですけど😅
このアプリ内の処理で気になる箇所(どうやって実装してるの?とか)があればお気軽にどうぞ!

I'm home! UNITY-CHANをリリース

久しぶりの投稿となってしまいましたが、I'm home! UNITY-CHANというアプリをリリースしました!
特別、技術的に難しいことは何もしていませんが、cocos2d-x ver 3.16を使用しております。
今まではver 2系しか使用したことがなかったため、その勉強も兼ねて。
パズルアクションとなっておりますので、手軽に遊べるかと!
このアプリ内の処理で気になる箇所(どうやって実装してるの?とか)があればお気軽にどうぞ!