ビギグラマーのノート

自作PCやプログラミングについてのブログです。

ContainerViewとSegue

環境 Xcode 8.2.1 Swift 3.0.2

 Segueで値を受け渡しするときに受け渡し先にContainerViewが存在し、そのClass内でSegueで渡す値を使用する場合ContainerViewの読み込まれる順番を考慮しないといけません。

f:id:BegiGrammer:20170209133707p:plain

  読み込まれる順番としては

  1. Segueのタイミング
  2. ContainerViewのViewDidLoad
  3. ViewControllerのViewDidLoad
  4. ViewControllerのViewWillAppear
  5. ContainerViewのViewWillAppear

 このようになります。私は最初ViewControllerのViewDidLoadが読み込まれると思い、ViewControllerのViewDidLoad内でstaticにした変数にSegueで送られた値を入れ、ContainerViewのViewDidLoadでインスタンス化しその変数を取得する方法を試しました。しかし上記の順番を見れば一目瞭然なように、これではSegueで送られた値が正常にContainerView内で読み込まれません。

 解決方法としてViewControllerとContainerViewControllerをつなぐEmbed Segueを利用してViewControllerで受け取った値をContainerViewControllerに受け渡します。言葉にするよりコードを見てもらった方が早いですね。

f:id:BegiGrammer:20170209141720p:plain

 これでFirstViewController → ViewController → ContainerViewControllerへの値の受け渡しが正常に完了しました。

KP41病

KP41病はWinで悪名の高い「Something is happen」な病気ですが、今回私のPCがこれにかかりました。最初は7Days to Dieをやりながらニコ動を見ていたのですが、途中でブラックアウトしました。それからは数回起動に失敗し、起動しては数分で落ちるかブルスクを吐くを繰り返していました。そこで私が行った治療は、

  1. ドライバを手当たり次第にアップデートしていく
  2. Windowsの電源設定を見直してみる
  3. WindowsUpdateをする
  4. 全てのUSBを抜いて起動してみる
  5. メモリの電圧を上げてみる
  6. 一度組み直してみる
  7. Windowsクリーンインストールする
  8. 仮装メモリを0にし、SuperFetchを無効にする
  9. BISOを更新する

最後のBIOSの更新でしばらく調子が良くなっています。

私の経験ではKP41やブラックアウト、ブルースクリーン、勝手に再起動は基本的にはメモリ関連が何かおかしいか電源装置がバテていることが多かったと思います。過去に私はKP41のせいで2つの電源装置と1つのMBを交換しました。

 

今回の不具合はおそらくMini ITXという限られたスペース内にGTX1080と6700Kという普通ミドルタワー以上で運用するものを詰め込んだため何らかの給電装置(MBか電源)が熱によって急速に劣化した?それかもともとトラブルを抱えておりそれが熱によって表面化した?

BIOSの更新でしばらくは動くようになったのでOCCTなどで電圧を観察すればいいかな。(というかおそらくGigabyteの安物MBのせい。6700k動かすのに補助電源が半分しかないし...) 電源は使わないATXがあるからそれで確かめれるか...

CPUならBIOSが動かないだろうし、GPUなら単に画面が崩れたり操作できるけど真っ暗になったりするだろうから。

 

約一ヶ月前におそらく竜巻による落雷?か、私の住んでいるブロックが寒さで停電した時にAsrock Z170 Gaming ITXとi7 6700k、DDR4-3200 16GBメモリ 計6万円を溶かしているのでこれ以上の出費を抑えたかったのですが、一応大丈夫そうで一安心しています。しかし次回このようなことがあれば即電源とMBを変える予定です。(安物であまり良くなかったし...)

 

追記

健康なはずの予備の電源で20分くらい動いたのでそのすきにOCCTやりながら各電圧を計測しました。+12Vはなぜか計測できませんでしたが、+5Vと+3Vが異常に低い値を示していました。

他の人がOCCTのPower Supplyをした時の+5Vの画像を見ると4.9Vあたりを示しているので、間違いなくKP41病の原因はこの+3Vと+5Vです。(+12Vも異常かも・・・ 

以下の記録を計測したのは使っていなかった予備のCORSAIR AX760です。(SFX電源に帰るまで使っていましたが普通に使えていた電源です)

f:id:BegiGrammer:20170204053658p:plain

f:id:BegiGrammer:20170204053705p:plain

なので、MBを交換する事になりました。2017年2月15日発売予定の EVGA Z270 Stinger がM.2 やWifi (U2はいらないのですが...)  3つのPMWファンコネクタがついていて良さげなのでそれを買う予定です。EVGAは保証が最高ですし。無いとは思いますが、電源が両方壊れていた場合はSilverstone SFX 600wにしようかと思います。Corsair SFX 600と比べてケーブルが柔らかく取り回ししやすいそうです。

実家なら工具が一通り揃っていて色々電源を弄れるのですが、現在寮住みなのではんだくらいしかまともなものがありません。テスターを買えば電源の異常か確かめられるのですがその数千円が惜しいのです。

 

未来の私のためにKP41病の検証の仕方を残しておきます。

  • Windowsの省電力関係の設定を見直す
    Windows Updateで設定が勝手に変えられることもあり要確認
  • ドライバアップデートを確認
    特にGPU関連のアップデートに気をつける
  • COMSクリアをする
  • 最小構成で確認
  • とりあえず1日電源を全て抜いて放置
  • メモリの電圧を5%ほど上げてみる
    ただしこの方法は対処療法程度にしかならない可能性がある
  • OCCTのPower Supplyを実行して各電圧を確認
    これで異常が出た場合、電源装置かMBの不具合だとわかる
  • もう一度組み直してみる
    案外コードが外れかけていただけということもある
  • 電源装置を予備のものと変え、再びOCCTで電圧監視
    これで電圧が異常だった場合は大体MBの不具合
    一応、電源装置単体でスイッチ用端子をショートさせて電圧をテスターで測る (負荷をかけた場合の電圧は分からないが念のため)

 

-後日談

 Stingerの発売を待ちきれなかった私は結局ASUS Z170 Gaming ITXを購入しました。4ピンのファンもCPU用と合わせて3つありますし、Asrock, MSI, Gigabyteときて初めてのASUSですから。

 KP41病は発病することなく、上で問題になっていたOCCTでいじめた際の電圧低下も今の所起こっていません。すなわち今回の病気の原因はズバリMBでした。

 

-追記

 なんやかんやあって結局一番最初に買ったAsrock Z170 Gaming-ITXを買い直し組みd立てたところ動きませんでした。理由は今まで散々耐え抜いてきたCPUがいかれたことと、メモリがおそらく熱によって故障したからです。ITXのスリムケースでGTX1080とi7 6700Kの組み合わせは排熱が結構ネックになってくることを約10万ちょいの勉強料を支払い思い知らされました。ただ一つ喜ぶことがあります。停電によって故障したと思っていた先代の6700Kが実は生きていました。(メモリなしのビープ音のチェックで死亡確認をしたと思うんだけどな〜)

 

コードで画面遷移 -マニュアルSegue-

環境 Swift 3.0.2 xcode 8.2.1

ちょっと引っかかったのでボタンなどで画面遷移ではなく、好きなタイミングで画面遷移する方法を書いておきます。

"autoSegue"は実行したいSegueのidentifier

コメントでも書いた通り、viewDidLoad内でpreformSegueを実行すると「Who view is not in the window hierarchy」になります。画面が表示されていないのに次の画面に移ろうと認め正常に動かないようです。なのでviewDidAppear内で画面表示後に自動画面遷移をしなくてはなりません。

画面の読み込み等の順番はここを参考にしました。

blog.livedoor.jp

すなわち何でもかんでも初めから書いてあるviewDidLoad内でやろうとしないこと、ということです。

アラートメッセージを作成

環境 Swift 3.0.2 xCode 8.2.1

C#などでは結構簡単にメッセージが書けましたが、Swiftでは結構量を書かなければなりません。

まずメッセージボックス内にテキストフィールドがないタイプ。

 

次はテキストフィールドが付いているバージョン

NOを選択したのにテキストフィールドのテキストが取得されるのはご愛嬌ということで。

CSVファイルの読み込みと変換

環境 Swift 3.0.2 xCode 8.2.1

今回やることは

  1. Documents内のファイルのパスを作成
  2. そのパスからファイルの存在を確認
  3. String型でCVSファイルを取得
  4. indexで各文字をCharacter型で取得
  5. カンマやダブルクォートなら仕様通りに前後を確認し編集

indexで文字を検索するのは多機能ですが行を使うので簡単な関数を作っておきます。

 

多次元配列の初期化で var array1 : String = ; array1.append(Array<String>()); を使っていますが、以前のバージョンで実行結果が[,["A","B"],["C","D"]]のように思うような形にならなかったりしました。なので今回はうまくいきましたが将来的にはどうなるかわかりません。

今回はindexで文字を一個一個取り出してStringの変数に加えていく形にしましたが、レンジ演算子で範囲指定でうまくやればもっとスマートにできそうです。

 今回はCVSの仕様の一つであるダブルクォートでセルを囲むタイプを読み込みましたが、この他にもダブルクォートで囲まないものや、マイナーですがTabで囲むものなどがありこれらに対応するものも作らなければいけません。switch部分に機能を足していけば結構簡単に実現できそうです。

毎回case 「ダブルクォート」の際に2つ後の文字まで確認するため最後でindex外の数値を指定し Error : The index is too big を吐いていますが、予想通りなので問題ありません。最後のダブルクォートでその定数を作るのを止めればいいのですが、あらかた書き終わった時点で気がついたので直す気力がなくなりました。wordIndex関数で範囲外のは弾いているのでまあ良しとしましょう。

*追記*

 このCSVファイル読み込み関数を使用する場合、読み込ませるCSVファイルは

  • 文字コードUNICODE
  • セルをダブルクォートで囲む
  • セル内でダブルクォートを使用する場合二重につける ""
  • ヘッダはつけない

を前提にしてファイルを作成してください。

Documents下に多次元配列からCSVファイルを作る

環境 swift 3.0.2 xCode 8.2.1 対象 iOS10.2

 

 

二次元配列からcsvファイルを作成するコードです。場所はDocuments下になるので主にユーザーが編集できる場所になります。

仕組みとしては

  1. ファイルを保存するパスを作成
  2. 二次元配列のfileArrDataをcsv用に「,」や改行を入れてString型のfileStrDataに入れる
  3. 作成したパスにcsv形式でwriteする

これは単にTest用のswiftファイルで関数を作っているため、同名ファイルを作った時の警告等のUIに深く関わってくるところはのぞいています。 あと、セルをダブルクォートで囲む理由はカンマを使用した際に崩れるのを防止するためです。詳しくはWiki等のCSVの仕様を確認してください。他のこの仕様に対応していないプログラムでファイルを作ってそれを読み込む場合も作らなければなりません。(カンマを使っていたら崩れてしまいますが諦めるほかありません

 

追記- 2日後

 

 これでDocumentsのファイルを全て調べることができる。本来ならCSVファイルしか読み取らないようにする予定だったが、まあいいや。それはテーブルでゴニョゴニョするとき、拡張子をもぎ取る必要があるからそのとき振り分けってことで。

最初は二進も三進も分からず、BundleクラスのBandle.main.pathsで探そうとしたけどBundleってつまりアプリの要素としてバンドルされているものを探すもの。だからDocuments内は探せない。その場合はFileManagerを使う。

余談だがFileManagerクラスのURLをWeb限定の用語だと思っていたが、ディスク上にあるローカルなファイルや、リモートのファイルなども扱えるらしい。(読み込み不足・・・

TableViewの画面遷移と値渡し

iOS 10.1 Xcode 8.0 Swift 3.0.2

 一つ目のViewControllerにTableViewを作成し終わっていることを前提として説明し始めます。まだな人はここを参考にするといいかもしれません。ここではTableViewのCellを選択した際に画面遷移させる方法と、また同時に選択されたCellの情報を渡す方法を解説します。 

 右下のLiblaryからViewControllerを引っ張ってきて貼り付けます。それにCellから引っ張ってきて紐付けをします。

f:id:BegiGrammer:20161224231659p:plain

ここではとりあえずShowを選択してください。ここのSelection SegueのSegueとは画面遷移のことを指します。そして2枚目のViewControllerのClassを新しくClassファイルを作成してこれを設定します。ここではとりあえずSecondViewControllerとします。

f:id:BegiGrammer:20161224232320p:plain

ここまでは以前詳しく解説したので駆け足で通り抜けました。

ViewControllerとSecondをつなぐSegueを選択しidentifierをつけます。

f:id:BegiGrammer:20161224232730p:plain

そしてViewController.swiftを編集して行きます。ここが今回のSegueのメインテーマになります。

f:id:BegiGrammer:20161224232920p:plain

古い情報ではprepareForSegue関数を使っていましたが、私の環境では使用できなかったのでprepare()を使います。機能はprepareForSegueと同じでSegueされる際に呼び出されることになります。if segue.identifier == "segue1"{}はこのprepare()はどのようなSegueでも呼び出されるのでidentifierを識別することで正しい代入が行われるようにしています。

print()は後々呼び出される順番を見極めるために使用しました。

resultは 配列[indexPath.row]の選択されたものを一時的に保管するための変数になります。

secondViewController.recievedはSecondViewController.swiftに書いたcellの情報を受け取るための変数です。

f:id:BegiGrammer:20161224233839p:plain

 

prepare()をViewControllerクラスの中に書いてCellの結果をSecondViewControllerクラスのreceivedに代入してあげれば完了ですが、resultにCellの選択結果を代入してあげるタイミングがdidSelectRowAtが呼び出される時だとすでにprepare()が呼び出されています。すなわちsecondのviewDidLoad()に間に合わなくなってきます。

なのでこの場合代入するタイミングはdidHighlightRowAtとなります。

 tableView.deselectRow()を実行することでTableのハイライトが解除されます。(これをしておかないと審査の時に落とされるそうです)

 self.dismiss()を実行することで元いたView(この場合ViewController)に戻れます。私はBarにその機能をつけました。