ビギグラマーのノート

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

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にその機能をつけました。

Table View の使い方

環境 iOS 10.1 Xcode 8.0 Swift 3.0.2

前回Table View Controllerの使い方を説明しましたが、実はあれには重大な欠点があります。それは実行した際にステータスバーにかぶることです。この原因は本来ならViewが土台にあってそこにペタペタ貼り付けていくのですが、Table View Controllerはその土台のViewがないためTable Viewのみ(余白すらなし) の画面が出来上がるためです。

f:id:BegiGrammer:20161217002343p:plain

実際にTable View ControllerのTableをサイズ変更しようとしてもできないはずです。

そこで今回は土台となるViewがあらかじめ貼り付けてあるView ControllerにTableを貼り付けて使用するための方法を紹介します。(といってもあの雛形からC&Pしてくるだけですが... ViewクラスにTableを入れるということです。

まずView ControllerにTableをはり、その上にCellを配置します。

紐付けはこんな感じに

f:id:BegiGrammer:20161217003128p:plain

コードはこんなん

f:id:BegiGrammer:20161217003156p:plain

補足説明として、indexPath.rowには配列の番号が入る。textLabel?の?はnil(null)が入るかもしれないど... ということ !は逆で関数を強制的に開封してnilが入っていないことを確認する。

 

この時UITableViewDataSourceとUITableViewDelegateのクラスの継承を忘れるとSIGABRTになります。

[ to be continue]

Table View Controllerの追加と使いかた

iOS 10.1 Xcode 8.0 Swift 3.0.2

Table View ControllerをSingle View Applicationを選択して作ったStoryboardに追加し実際に使う方法を残しておきます。

まずLibrary paneからTable View ControllerをStoryboradにD&Dしてきます。ここにデフォルトのスタート位置であるView Controller Sceneに適当なボタンを設置してそこからTable Viewに引っ張ってきます。

f:id:BegiGrammer:20161213193928p:plain

この状態でシュミレートすると何も入っていないテーブルが並んでいるのが見えるはずです。

これを制御していくためのファイルを作ります。ツールバーのFile > New > File でCocoa Touch Classを選択しNext.

f:id:BegiGrammer:20161213194446p:plain

Classに適当な名前をつけ、Subclass of : UITableViewControllerを選択 Creatすると雛形ファイルが作成されます。

Storyboradに戻り、Inspector BarでShow the identity inspectorを選択Classの選択欄で作成したClassファイルを選択します。

f:id:BegiGrammer:20161213195129p:plain

 

Table View CellのInspector BarでShow the Attributes Inspectorを選択し、Identifierに適当な名前をつけます。

f:id:BegiGrammer:20161213195809p:plain

先ほど作ったClassファイルへ移動します。ご丁寧に雛形を作っていてくれるので単に値を入力するだけで済みそうです。あと必要な機能はコメントを外しましょう。

初めてではアレルギーが発症しそうな感じですが、上の方はViewContoroller.swiftと同じです。まず5段目の関数のコメントを外しましょう。ここではTableに入力するTextを扱います。

f:id:BegiGrammer:20161213200611p:plain

まず、適当な配列を作成しましょう。

let Eworda = ["long", "short", "light", "heavy"]

次にnumberOfSectionsとtableView関数をいじっていきます。これらはそれぞれ[配列を何回表示するか], [配列に何個の要素があるか]をreturn部分に入力します。すなわち通常ならnumberOfSectionsには1を、tableViewには 配列名.count を入力します。

f:id:BegiGrammer:20161213201842p:plain"resuseIdentifier"に先ほどTable View Cellにつけた識別名を入力してください。(私の場合BBWordsです)

さらに同じ同じ場所に

cell.textLabel!.text = 配列名[indexPath.row]

で返すcellに配列のtextを入力します。

f:id:BegiGrammer:20161213202304p:plain

 

Table View Controllerを使わないバージョン

(Cellをクリックした時の動作も以下のリンクで解説)

begigrammer.hatenablog.com

 

 

Tap Gesture Recognizer

環境 iOS 10.1 Xcode 8.0 Swift 3.0.2

バイス画面をタップした際のactionを決定する。

f:id:BegiGrammer:20161212201946p:plain

いわばシーンの一部と同じように扱われる。

Sent ActionsをViewController.swiftに引っ張ってくることで使用可能。

 

例えば一回タップして表示を変え、もう一回タップして表示を更に帰る機能はこれ自体には当然ないわけで、呼び出し回数を数えて表示を変える関数が必要。

ちなみにSwiftのデータ型は大文字から始まる。(勝手に修正してくれればいいのに..

ループものでよく使うnum++はswift3で削除された。代わりに num += 1

switch文では各ケース毎にbreakしなくてもいっちゃわない。(フォールスルーというらしい) 何もしないcaseの場合はbreakをすること

 

簡単な戻ってくる機能(Note Taking用

loadRequestでwebにアクセスできない

環境 iOS 10.1 Xcode 8.0 Swift 3.0.2

 

ios9以上ではUIWebViewを使用してインターネット閲覧機能をAppに実装するとき、loadRequestをしてHTTPウェブサイトにアクセスできません。その場合info.plistを書き換えて一時的にHTTPにアクセスすることを許可しないといけません。言い換えればHTTPSのサイトにはそのままアクセスできるということです。

HTTPSとはSSLによる通信の暗号化を行いより安全に通信をできるようになる仕組みです。しかし現在のところHTTPS通信に全てのサイトが対応しているとは言いがたい状態です。

f:id:BegiGrammer:20161210174356p:plain

Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can ve configured via your app's Info.plist file.

すなわち「HTTPなんて信用できるかFu*k  でも、Info.plistで許可してくれたら考えておくけど... 別にあんたのためじゃないんだからね!あくまで一時的によ 一時的に...

ということをおっしゃっているようです。すなわちinfoを編集しなくても例えば、 https://www.amazon.com などのHTTPS通信に対応しているところにはアクセスできます。

以下 info.plistの編集方法

f:id:BegiGrammer:20161210180753p:plain

info.plist にApp Transport Security Settingsを追加し(追加方法はカーソルを合わせると出てくる+ -の+をクリック)その中にさらにAllow Arbitarary Loadsを入れ、そのValueをYesに変更してください。

f:id:BegiGrammer:20161210181238p:plain

この方法は前述の通り一時的なものなので将来的には削除される可能性があります。 

現在UIWebviewからWKWebviewに移行が進んでおり、全体的にそちらの方がレスポンスも早く、なおかつ安定しているそうです。