- 投稿日:2020-06-01T23:55:05+09:00
components(separatedBy: CharacterSet.decimalDigits.inverted)って何? と思ったら文字列分解についてよく理解していなかった話
※本記事のコードにおいて、
import Foundation
は省略しています。はじめに
components(separatedBy: CharacterSet.decimalDigits.inverted)
を読んでも処理結果がよく分からず記事を書こうとしたのですが、記事を書いてる途中でメソッド自身ではなく、文字列分解がよく理解していないことが分かりました。
本記事では文字列分解について、具体的には区切り文字が連続する際の文字列分解の処理について記載しました。
components
の使い方も共に追っていきます。componentsとは
文字列処理のメソッド
components(separatedBy:) - NSString | Apple Developer Documentationcomponents(separatedBy: "文字列")
let str = "ac7wa20tle7mle" let result = str.components(separatedBy: "7") // ["ac", "wa20tle", "mle"]区切り文字:任意の文字列
components(separatedBy: CharacterSet.decimalDigits)
let str = "ac7wa20tle7mle" let result = str.components(separatedBy: CharacterSet.decimalDigits) // ["ac", "wa", "", "tle", "mle"]区切り文字:10進数字の文字列
decimalDigits - NSCharacterSet | Apple Developer Documentationcomponents(separatedBy: CharacterSet.decimalDigits.inverted)
let str = "ac7wa20tle7mle" let result = str.components(separatedBy: CharacterSet.decimalDigits.inverted) // ["", "", "7", "", "20", "", "", "7", "", "", ""]本題。
inverted()
から反転が分かる、つまり10進数字外の文字を区切り文字としています。よく分からないので短い文字列で見てみます。
let str = "ac7" let result = str.components(separatedBy: CharacterSet.decimalDigits.inverted) // ["", "", "7"]?(空文字どこから来たのだろう?)
前から見ていきます。
初期状態
"ac7"
"a"
の前後の領域を区切る。
""
,"a"
,"c7"
"a"
を除く
""
,"c7"
"c"
の前後の領域を区切る。
""
,""
,"c"
,"7"
"c"
を除く (最終形)
""
,""
,"7"
別の例で考えてみる。
"7/7" sep="/"
let str = "7/7" let result = str.components(separatedBy: "/") // ["7", "7"]分かる。
"7//7" sep="/"
let str = "7//7" let result = str.components(separatedBy: "/") // ["7", "", "7"]
初期状態
"7//7"
"7"
は区切り文字ではないのでパス
"7//7"
"/"の前後の領域を区切る
"7"
,"/"
,"/7"
"/"
を除く
"7"
,"/7"
"/"の前後の領域を区切る
`"7"
,""
,"/"
,"7"
"/"
を除く (最終形)
`"7"
,""
,"7"
つまり、連続する区切り文字がある場合、{連続する個数-1}個分の空文字が生成されることになります。
…とは必ずしも言い切れません。次の例で考えてみます。"/7/7" sep="/"
let str = "/7/7" let result = str.components(separatedBy: "/") // ["", "7", "7"]
初期状態
"/7/7"
"/"の前後の領域を区切る
""
,"/"
,"7/7"
"/"
を除く
""
,"7/7"
(WIP) と同じ。 (最終形)
""
,"7"
,"7"
つまり、先頭と末尾には
""
が暗黙的に存在しているので下記のように言い表すことが出来ます。区切り文字が連続しているときに生成される空行の個数は、
- 連続する区切り文字が先頭、末尾に含まれない時: {連続する個数-1}個
- 含まれる時: {連続する個数}個
となります。
おわりに
冒頭にもありますが、文字列分解についての記事になりました。
区切り文字が連続するケースについて考えたことがありませんでした。
- 投稿日:2020-06-01T23:36:46+09:00
【xcode】swift5 BGMを流したまま効果音を鳴らす
やりたいこと
BGMを流したまま効果音を再生する
ソースコード
音声のファイル名:bgm.mp3と button.mp3
import UIKit import AVFoundation class ViewController: UIViewController { var player0:AVAudioPlayer? var player1:AVAudioPlayer? override func viewDidLoad() { super.viewDidLoad() // 再生する音声ファイルを指定する let url = Bundle.main.bundleURL.appendingPathComponent("bgm.mp3") do { try player0 = AVAudioPlayer(contentsOf: url) } catch { print("Error") } player0!.play() //音声をループさせる player0!.numberOfLoops = -1} //ボタンを押したら効果音がなるように設定 @IBAction func playSound(sender: AnyObject) { // 再生する音声ファイルを指定する let soundURL = Bundle.main.url(forResource: "button", withExtension: "mp3") do { player1 = try AVAudioPlayer(contentsOf: soundURL!) player1?.play() } catch { print("error...") } } }まとめ
音を同時に再生しようとすると片方の音が止まってしまう問題に約1時間もハマってしまいました。
色々調べた結果【作るAVAudioPlayerのインスタンスの数だけ音楽再生関数を作る必要がある】とのことで上記のようなコードに至りました。
意外とシンプルだった。出来た時めっちゃ嬉しかったです。笑初心者なので上記のコードがベストなのかはわからないのですがとりあえず動いたから良いと言うことで。笑
より良い同時再生方法があればご教授いただけると嬉しいです。
- 投稿日:2020-06-01T23:08:51+09:00
iOSアプリ ノッチ判定
はじめに
アプリ完成間際、ノッチの存在に気付き実装しました。
忘れがちなので、気をつけたいです。やりたいこと
iPhoneX以降、ノッチが出現したことにより、画面上部ぎりぎりに配置すると、
ノッチと被ってしまい画面上に表示されなくなってしまいます。
なので、ノッチがあるかないかを判定して、
ノッチがある場合 → ノッチ分(44pixel)ずらす
ノッチがない場合 → 画面上部ギリギリに配置という方法をとることにしました。
実装
view.swiftclass view: UIViewController { let text = UILabel() override func viewDidLoad() { //safeAreaの値を取得します。 let safeAreaInsets = UIApplication.shared.keyWindow?.safeAreaInsets.left super.viewDidLoad() //safeAreaの値が44.0以上であれば、ノッチがあるので、x位置をずらします。 if(safeAreaInsets! >= 44.0){ text.frame = CGRect(x:50,y:width/2, width:self.view.frame.height,height: 50) } //ノッチがない場合の処理 else{ text.frame = CGRect(x:10,y:width/2, width:self.view.frame.height,height: 50) } }ノッチの値が44なので、今回は50ずらしました。
- 投稿日:2020-06-01T22:09:55+09:00
【Swift】WordPressにAPIリクエストをしてブログ情報を取得する
APIリクエストの飛ばし方がやっとわかった
Swiftには便利なライブラリAlamofireというものがあり、それを使用してHTTP接続をするのがセオリーですが、いかんせん最近はAlamofireの書き方が新しくなり、ネットでも調べても全然よくわかりませんでした。
それがやっと解消できたのでここに記します。WprdPressが提供してくれてるAPI
情報が欲しいブログのURLの後ろに「/wp-json/wp/v2/posts?_embed」をつけてあげて、そのURLにリクエストを飛ばします。
私のブログはkimotii.comなので、kimotii.com/wp-json/wp/v2/posts?_embedとなります。
ライブラリを入れる
CocoaPodsを使って便利なライブラリを入れましょう。
今回使用するのは
・Alamofire
・SwiftyJson
の2つです。
手順は、1、ターミナルで以下を打つ
sudo gem install cocoapodsインストールが終わったら
pod setup2、Xcode開いて今回作りたいアプリのプロジェクトを作る
ホームに作ると楽3、ターミナルで
cd プロジェクトフォルダの名前フォルダに移動できたら
pod initこれでpodファイルが生まれる
4、podファイルを開いて、
pod 'Alamofire' pod 'SwiftyJson'これらを記入したら
pod installこれでライブラリがインストールされました。
書いてみよう
以下が今回書いたものです。記事のタイトルを全て出してみました。
import UIKit import Alamofire import SwiftyJSON class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() // APIリクエストの関数を呼び出す getArticles() } func getArticles() { // Alamofireを使う // URLでリクエストを飛ばし、レスポンスがresponseに入る AF.request("https://kimotii.com/wp-json/wp/v2/posts?_embed").responseJSON { response in // 確認のためresponseを見てみる print("Response JSON: \(response.value)") // responseがnilじゃなかったら変数jsonObjectにレスポンスを入れる if let jsonObject = response.value { // 変数jsonにJSON形式にしたjsonObjectを入れる let json = JSON(jsonObject) // 配列の数だけ処理を繰り返す for i in 0..<json.count { let array = json[i] // "taitle"の"rendered"を指定してあげると記事タイトルが取れる let title = array["title"]["rendered"].stringValue // 取得できたタイトルを表示 print(title) } } } } }タイトル以外にも色んな情報がとれるのでおためしあれ!
- 投稿日:2020-06-01T21:42:13+09:00
【Swift5�】 特定画面で縦画面/横画面に固定させる
はじめに
初投稿です。
ついにやってみたかったiPhoneのアプリを完成できました!
その備忘録です〜やりたかったこと
ゲーム設定画面は縦、ゲーム画面自体は横画面としたかったので、
画面の向きを判定して、縦だったら横に、横だったら縦に向きを固定する。
※便宜上、
ホームボタン左 = 左横画面
ホームボタン右 = 右横画面 とします。やってみたこと
supportedInterfaceOrientationsの単純な画面の向きを指定だけだと、
自動回転しちゃうのでそれも制御しないとだめなんですよね。view.swift// 画面の向きを指定 override var supportedInterfaceOrientations: UIInterfaceOrientationMask { return .portrait } // 画面を回転させるかどうか override var shouldAutorotate: Bool { return true }単純にこれでいけそう!とか思ってたんですけど、
どうも処理の順番が
shouldAutorotate(自動回転) → supportedInterfaceOrientations(向き指定)らしく
自動回転OFF → 縦画面に変更
になって、回転できないんですよね〜とほほなので、代案として現在の画面向きを取得して、以下の通りの処理を考えました。
画面 現在の画面向き 実装 縦 縦の場合 自動回転OFF 縦 横の場合 画面向きを縦にして自動回転をOFF 横 縦の場合 画面向きを横にして自動回転をOFF 横 横の場合 自動回転させる 実装コード
縦画面
TateViewController.swiftclass TateViewController: UIViewController{ // 自動回転はOFFで縦に固定 override var shouldAutorotate: Bool { //縦画面なので縦に固定 UIDevice.current.setValue(1, forKey: "orientation") return false } override func viewDidLoad() { <<Code>> } }画面を縦に固定なら自動回転ON/OFF決めるときに
縦にして自動回転OFFにすればいいじゃん!と思ってゴリ押しでオーバーライドしました。解決!横画面
YokoViewController.swiftclass YokoViewController: UIViewController { override var supportedInterfaceOrientations: UIInterfaceOrientationMask { //最初の画面呼び出しで画面を右横画面に変更させる。 UIDevice.current.setValue(3, forKey: "orientation") return .landscapeRight } // 画面を自動で回転させるかを決定する。 override var shouldAutorotate: Bool { //画面が縦だった場合は回転させない if(UIDevice.current.orientation.rawValue == 1){ return false } else{ return true } } }横画面のほうはちょっとめんどくさくなりました。
shouldAutorotateは画面回転ごとに呼び出されるので、画面回転すれば、横画面にすることができます。if条件で縦のとき自動回転OFFにすれば、縦に回転しません。ただ、最初の画面遷移時に、自動回転OFF→縦画面に変更の順に処理されるので、先に横画面の変更処理をする必要があります。どうしたものか...
横画面 自動回転先呼び出し
適当にTry&Errorを繰り返してたら、viewDidLoad()内でprint()することで
画面の自動回転定義(shouldAutorotate)より先に呼び出すことができました。いい子。YokoViewController.swiftoverride func viewDidLoad() { //画面の向きを変更させるために呼び出す。 print(supportedInterfaceOrientations) <<Code>> }横画面 右左判定
ただ、横向きでまとめてしまうと、現在の画面向きが左横画面なのに、右横画面だと逆向きになってしまいます。なので左横画面とそれ以外で場合分けしました。
YokoViewController.swiftoverride var supportedInterfaceOrientations: UIInterfaceOrientationMask { //左横画面に変更 if(UIDevice.current.orientation.rawValue == 4){ UIDevice.current.setValue(4, forKey: "orientation") return .landscapeLeft } //左横画面以外の処理 else { //右横画面に変更させる。 UIDevice.current.setValue(3, forKey: "orientation") return .landscapeRight } }それでうまく行くと思いきや、前画面で縦に指定しているので
画面向き判定が「縦」になってしまいます。なので強制的に右向き画面になります。こまった。横画面 左横画面にセット
そこでviewDidLoad()内で以下の処理をします。
YokoViewController.swiftoverride func viewDidLoad() { //画面向きを左横画面でセットする UIDevice.current.setValue(4, forKey: "orientation") //画面の向きを変更させるために呼び出す。 print(supportedInterfaceOrientations) <<Code>> }縦画面で遷移している前提ですが、一度強制的に左横画面にセットします。
自動回転は縦画面でなければ、回転するので左横画面になった後右横画面に自動的に回転します。解決!以下横画面のソースコード全文です。
YokoViewController.swiftclass YokoViewController: UIViewController { override var supportedInterfaceOrientations: UIInterfaceOrientationMask { //左横画面に変更 if(UIDevice.current.orientation.rawValue == 4){ UIDevice.current.setValue(4, forKey: "orientation") return .landscapeLeft } //左横画面以外の処理 else { //最初の画面呼び出しで画面を右横画面に変更させる。 UIDevice.current.setValue(3, forKey: "orientation") return .landscapeRight } } // 画面を自動で回転させるかを決定する。 override var shouldAutorotate: Bool { //画面が縦だった場合は回転させない if(UIDevice.current.orientation.rawValue == 1){ return false } else{ return true } } override func viewDidLoad() { //画面向きを左横画面でセットする UIDevice.current.setValue(4, forKey: "orientation") //画面の向きを変更させるために呼び出す。 print(supportedInterfaceOrientations) <<Code>> } }なんとかできました。
参考にした記事
- 投稿日:2020-06-01T21:16:58+09:00
【プログラミング初心者】Swift基礎~メソッド・関数~
はじめに
今回はSwiftでのメソッド作成方法についていくつか紹介します。
メソッド・関数とは
関数
そもそも関数がどういうものか説明します。
簡単にいうと処理の塊です。
プログラムにはmain関数と呼ばれるプログラムを実行した時最初に呼ばれる処理があります。
(iOSアプリをSwiftで開発する場合は内部で定義されているので見れませんが)
極論をいうとこのmain関数さえあれば関数を使わなくてもプログラムは書けます。ですが現実的に数万行に及ぶ処理がずらずらと書かれていても処理を把握することは困難です。
そのため関数に処理を分けてあげて関係する処理を分割してあげています。さらに同じ処理をする場合は関数に書くことで重複するコードを書かなくて済みます。
関数は数学で使っていた関数と似ており、何かInputを与えて処理の結果をOutputとして返します。
y = ax + b
という1次関数があります。
これはxに何かInputを与えた結果yというOutputを得るという処理です。
これをプログラムで書くと以下になります。let a = 5 let b = 10 func linearFunction(x: Int) -> Int { return a * x + b } let y = linearFunction(x: 3)この何かしら処理をする
linearFunction
のようなものを関数と呼びます。引数
関数には必須ではありませんが引数を設定できます。
上記の例で言うとx: Int
が引数です。引数は関数へのInputです。
この与えられた引数を使って処理を制御します。
もちろん引数なしで制御可能な場合は定義しなくても問題ありません。
必要とする場合は型アノテーションが必須となります。与えられた引数は
let
つまり定数として定義されます。
従って変更することはできません。
あくまで与えられた値を使って何か処理をするという用途になります。また複数指定することができます。
複数指定する場合は以下のようになります。func function(arg1: Int, arg2: Int, arg3: String) { }戻り値・返り値
戻り値は関数からのOutputです。
関数が値を返してくる値を戻り値や返り値と呼びます。
戻り値なしの場合は不要ですが、戻り値がある場合は-> 戻り値の型
というように戻り値の型を明示する必要があります。func function(arg1: Int, arg2: Int, arg3: String) -> Int { }戻り値を設定した場合は必ず何かしらの値を返さなければなりません。
戻り値は
return 値
という構文で返します。
return
が呼ばれると後続の処理が呼ばれないので注意してください。func function(arg1: Int) -> Int { return arg1 + 1 print(arg1) // 実行されない }戻り値なし場合以下のように値なしreturnできます。
func function() { return }補足ですが戻り値の場合暗黙的に
Void
という戻り値が返っています。
これは何もないというような意味です。
なので上記の例は以下と同じ意味です。func function() -> Void { return }メソッド
メソッドというものもあります。
メソッドも関数の一種で、クラスが持つ関数のことです。基本的にSwiftはクラス内で関数を定義しているため、メソッドという言葉を使うことが多いです。
ですが関数といっても間違いではないので問題ありません。定義の仕方は関数と同じです。
呼び出し方
関数の場合、以下のようにそのまま直接呼び出すことができます。
var returnValue = function()
print()
なども関数なのでそのまま呼び出すことができます。メソッドの場合、
オブジェクト.関数名()
という形で呼び出します。let object = Object() let returnValue = object.function()クラス内で自分のメソッドを呼び出す場合は以下のようにします。
let returnValue = self.function()
self
は自分自身のオブジェクトを示します。他の言語だとthis
とかになったりします。
実はSwiftの場合self
を省略しても言語上問題ありません。SampleClass.swiftclass SampleClass { func function() -> Int { return 1 + 1 } func test() { let selfvalue = self.function() let noSelfValue = function() } }これはチームのコーディング規約に則って付けるか付けないか決めてください。
Swiftメソッド記法
Swiftは言語として少し特殊で引数の書き方がいくつかあります。
よく使う例を紹介していきます。デフォルト値指定
引数にデフォルト値を指定することができます。
デフォルトを設定した引数は引数なしで呼び出すことができます。func function(arg1: Int = 0, arg2: Int = 0) { print("arg1: \(arg1), arg2: \(arg2)") } self.function() // arg1: 0, arg2: 0 self.function(arg1: 10) // arg1: 10, arg2: 0 self.function(arg2: 10) // arg1: 0, arg2: 10 self.function(arg1: 10, arg2: 10) // arg1: 10, arg2: 10引数のラベルを省略
以下のように引数前に
_
をつけて定義すると、メソッドコールのとき引数のarg1:
というラベルを省略することができます。func function(_ arg1: Int, arg2: Int) { } self.function(1, arg2: 1) // OK self.function(1, 1) // NG self.function(arg1: 1, arg2: 1) // NG引数のラベルに別名を付ける
ラベルに別名をつけることができます。
func convert(from value: Int) -> String { return "\(value)" } let stringValue = self.convert(from: 1) // OK let stringValue = self.convert(value: 1) // NG補足ですが、この方法はSwfit特有のものではありますがよく使います。
よくfrom
to
with
のような前置詞を使って別名を付けメソッド自体が英文として読めるように書くことが多いかと思います。メソッドの引数について
以前変数がどのようにメモリに確保されるのかを説明しました。
メソッドの引数の場合はどうか見ていきます。値渡し
先述しましたが引数は
let
として新しく定義されているのと同義です。
そのため引数も変数もメモリ上の扱いは同じになります。以下のように構造体とメソッドを定義し呼び出してみます。
struct Dog { var name: String } func update(with newName: String, dog: Dog) { dog.name = newName } var myDog = Dog(name: "ポチ") print("更新前: " + myDog.name) self.update(with: "ミケ", dog: myDog) print("更新後: " + myDog.name)この場合メソッド定義の部分で
Cannot assign to property: 'dog' is a 'let' constant
とSwiftのエラーが発生し実行はできません。
これは引数がlet
で定義されているため発生したエラーです。
ですが、もし仮にSwiftがエラーを返さないと仮定します。
その場合であってもメソッド内のdog.name
は「ミケ」に更新されますが、元となっているmyDog.name
は更新されません。
これは構造体が値型のため引数として渡されたdog
はmyDog
のコピーとなっているためです。
従って仮に実行できたとすると以下のような出力になります。出力更新前: ポチ 更新後: ポチこのように値そのものを引数に渡すことを値渡しといいます。
参照渡し
ではクラスの場合はどうでしょう?
以下のようにクラスとメソッドを定義し呼び出してみます。class Cat { var name: String init(name: String) { self.name = name } } func update(with newName: String, cat: Cat) { cat.name = newName } var myCat = Cat(name: "タマ") print("更新前: " + myCat.name) self.update(with: "トラ", cat: myCat) print("更新後: " + myCat.name)これはエラーは発生しません。
クラスの場合、参照型のため変数がlet
で定義されていても変数の値そのものを書換えているわけではないのでこれを実行できます。
実行すると以下のように出力されます。出力更新前: タマ 更新後: トラ
myCat.name
の値が更新されていますね。
参照型は引数にはmyCat
へのアドレスをコピーとして渡しているため同じオブジェクトを参照しており、そのため内容の更新ができたというわけです。このように引数にアドレス、つまり参照を渡しているものを参照渡しと言います。
値型を参照渡ししたいときは?
基本的にはやりません。
その場合は以下のように戻り値として新しいオブジェクトを返すように実装する方法が一般的です。func update(with newName: String, dog: Dog) -> Dog { var newDog = dog newDog.name = newName return newDog } let myDog = Dog(name: "ポチ") let newDog = self.update(with: "ミケ", dog: myDog) print(newDog.name) // ミケそれでもどうしても構造体を参照渡ししたいということもあるかと思います。
その場合は以下の方法で実装できます。func update(with newName: String, dog: inout Dog) { dog.name = newName } var myDog = Dog(name: "ポチ") print(myDog.name) // ポチ self.update(with: "ミケ", dog: &myDog) print(myDog.name) // ミケ
update
実行前と後でmyDog.name
の値が変わっていることから参照渡しになったことがわかります。引数が
dog: inout Dog
となりました。
inout
を引数の型の前に付けると参照型という意味になります。引数に渡す値は
&myDog
となっています。
変数名の前に&
を付けるとその変数のアドレスを意味します。
myDogはスタック領域に確保されているのでそのスタック上のアドレスが引数として渡されました。
その結果参照渡しとなりname
を更新できるようになりました。最後に
今回はメソッドについて、またそのメソッドの定義の仕方や引数の性質について説明しました。
引数の定義の仕方はおそらくチームによって別れてくるところかもしれません。
どれでも書けるようにしておくのが無難と言えます。今回の内容は以上です。
本記事とは別でプログラミング未経験からiOSアプリ開発が行えるようになることを目的とした記事を連載しています。
連載は以下にまとめていますのでそちらも是非もご覧ください。
アジェンダ:https://qiita.com/euJcIKfcqwnzDui/items/0b480e96166e88945684
- 投稿日:2020-06-01T17:48:50+09:00
アプリ開発超初心者が休業中にiOSアプリを公開した話
iOSアプリ開発は初心者でもできる?
Yes
はじめに
先に結論から述べると100%できます。なぜなら、ボンクラの僕にもできたからです(笑)どのくらいボンクラかと言うと、普通運転免許?の学科試験に二度落ちたくらいです(笑)おそらく、この記事の読者のほうが何十倍も賢いことでしょう。
そんな僕がたった1ヶ月半でどうやって、自作アプリをApp store(アプリケーションのダウンロードサービス)に公開するまでに至ることができたのかを、勉強法やマインド面を中心に、専門用語は避けて語っていきたいと思います。
iOSアプリを開発してみたいけど何から始めたら良いのかわからなかったり、はじめてみたけれど、進め方がよくわからないと感じている方への助け舟となれたら嬉しいです。ただし、科学的根拠は一切ないので、一意見として受け止めてください(笑)用意するもの
アプリ開発において用意するものは以下の2点です。
パソコンに関しては、Windowsでできないこともないらしいですが、使い方ガイドや参考資料が豊富なためMacが望ましいです。また、iOSアプリを開発するための環境は、Xcodeを利用します。以下のURLからダウンロードページに飛べます。
1.Macのパソコン
2.Xcode(できれば最新バージョン)
[ダウンロード] https://apps.apple.com/jp/app/xcode/id497799835?mt=12
App storeに公開するためには上記の2点+Apple Developer(年会費:1万1800円)に登録する必要があります。実機実験やシミュレータの利用は登録しなくてもできます。詳しくはググってみてください。勉強法
僕の勉強法を大雑把に説明すると、以下の3つのステップです。
効率よく学習するコツは、ステップ③を重視することです。以下で説明します。① Swift(iOS開発用言語)の基礎学習
・「15時間でわかるSwift集中講座」(Swiftのバージョン間違った)著者:高橋広樹
・「本気ではじめるiPhoneアプリ作り」著者:西磨翁
・ドットインストール(動画学習)
②サンプルコードを写経する(mainはXcodeの使い方を学習)
③自作(バス時刻表アプリ)
かけた期間で言うと、①に2週間②に1~2週間③に2~3週間程度です。
自粛期間中と言うこともあり、1日の平均学習時間は3時間くらい取れていました。
ここで大事なことは③の自作の段階にすぐに移ることです。
多くの方が、理解していないのにできる訳ない(怒)と考えると思います。
確かにそうです。基礎がわかっていないのに作れるわけがありません。ここで言いたいことは、①の基礎学習期間に時間を使いすぎるな!と言うことです。
ここに時間を使いすぎる人の多くは、完璧に理解しないと、もしくは覚えないといけないと考えていると思います。しかし、はっきり言って、Swiftを完璧に理解してるエンジニアは、ほとんどいないですし、ましてやコードを全て暗記している人なんてSwiftの開発者ぐらいです(笑)多くのエンジニアは、ネットなり書籍なりを調べながら開発しています。iOS開発を仕事にしてバリバリお金を稼いでいる人たちがどうなのかはわかりませんが、その方達もはじめは、調べながら開発していたはずです。全てを理解しようとせずに、何となくわかってきたぞとフワッとした感じで十分です。英会話とは違って、コンピュータは入力を待ってくれます(笑)とにかく簡単なもので良いので、自作アプリを作ってみましょう。
とは言っても、学習能力には個人差あるし、「やっぱりどのくらい学習すれば良いかわからないよ」と言う方もいると思います。そこで、ボンクラの僕を最底辺として、学習量の目安を立てると、多くても上の3つの様な参考書(何でも良い)を一周すれば十分だと思います。理解力がある人は3つ目の動画学習だけで良いかもしれません。何を開発すれば良いの?
とにかく作れと言われても、何を作ったら良いのかわからないし、そもそも何が作れるのかもわからないと思います。iOSアプリでは情報さえあれば、基本的に何でも作れると言っても良いです。しかし、初学者にとって技術的に難しすぎると言ったことはあると思います。例えば、ネットと通信を行ったりするようなアプリは、サーバーサイドの知識もある程度はないといけないため、初学者には難しいかもしれません。したがって、自分ができそうなレベルのちょっと上のレベルくらいのものが良いと思います。初学者が比較的に作りやすいアプリを以下に書いてみました。アイデアが浮かなければ、他者が開発したアプリを真似してみるのもありだと思います。
・バス時刻表アプリ
・メモ機能アプリ
・現在位置取得(GPS)を利用したアプリ
・画像認識系アプリ
・計算アプリアプリを公開するためには
しかし、上記のようなアプリは世の中に無数にあり、そのまま公開するとなると難しいです。恐らく審査ではねられます。appleの審査にこのような項目があるからです。
4.1:模倣
4.2:必要最低限の機能しかない
そのため、何かひとつ独自性のある機能を足してあげたら良いと思います。僕が初めて、公開したアプリ(バス時刻表アプリ)もその程度のレベルでした。最後に
独学でプログラミングを学習しようと思うと、正直かなり根気がいります。実際に、プログラミングを学習したけれど、挫折する人がほとんどだそうです。その原因の一つとしては、一緒に勉強する仲間や指南してくれる人がいないからだと思います。そんな時は、オンライン上のセミナーに参加したり、SNSで志が同じ仲間を探してみたりすることでモチベーションを保てるのではないかと思います。プログラミングも言語の学習と同様で、学び続ければ必ず会話ができるようになります。一緒に頑張りましょう。
- 投稿日:2020-06-01T15:04:49+09:00
`if (a == 1 && a == 2 && a == 3)` は真か?
背景
なんだか面白そうな記事を見つけた
(a == 1 && a == 2 && a == 3)は真と評価できますか?
のでSwiftでやってみたコード
var b = 0 var a: Int { get { b += 1 return b } } if (a == 1 && a == 2 && a == 3) { print("Complete!") }解説
a
とは別で変数を用意(ここではb
)して、a
のgetterでb
をインクリメントし、b
をreturnする。
if文でa
を3回取得するが、その度にa
のgetterを通るため、取得されるa
の値は1ずつ増えていく。結果
まとめ
getterを使うと、if文の中で同じ変数でも、異なる値を取得できる?
p.s. 他にいい方法があれば教えてください!
- 投稿日:2020-06-01T15:01:40+09:00
SwiftUIでScrollViewするときに影が横に出ないなどのトラブル対処法
この記事で解決できそうなこと
せっかく影をつけたのに横に出てないから見栄えが悪い。
スクロールインジケータが画面内側に出ている。起きている問題の原因
SwiftUIのビューの周りにはframeと呼ばれる外枠が存在します。下の画像のように、デフォルトではビューの周りに存在しています。
frame()
モディファイアは外枠の大きさを変更することで中にあるビューの大きさを変更させるといったイメージですね。
これをスクロールビューで並べると、frameが画面全体に広がっていないので影が外側に出ない、インジケータが画面内に出現するというトラブルが起きます。
問題の解決方法
padding
モディファイアによってframeをビューより大きく設定する必要があります。
.padding(.init(top: 0, leading: 50, bottom: 0, trailing: 50))
のように、中身のビューのどのくらい外に外枠を配置するのか設定することができます。ソースコード
**padding``をコメントアウトすることで横に影が表示されるようになります。
import SwiftUI struct test: View { var body: some View { ScrollView{ VStack(spacing: 8){ ForEach(0..<15){ _ in Text("Hello, World!") .foregroundColor(.white) .frame(width: 300, height: 60) .background(Color.yellow) .padding(.init(top: 0, leading: 50, bottom: 0, trailing: 50)) .shadow(radius: 10) } } } } } struct test_Previews: PreviewProvider { static var previews: some View { test() } }
- 投稿日:2020-06-01T14:59:49+09:00
[Swift] クロージャ(Closures)の記法
クロージャ(Closures)ってなんだか色々書き方あってややこしいですよね。
というわけで整理してみます。想定読者
- Swiftの基本的な文法はなんとなく理解しているが、クロージャはややこしいな、という人
- Swiftはある程度書けるようになったけど、いまいちクロージャの書き方に自信がない人
- 他言語でプログラミング経験があり、これからSwiftを学びたい人
クロージャとは
Closures are self-contained blocks of functionality that can be passed around and used in your code.
Closures in Swift are similar to blocks in C and Objective-C and to lambdas in other programming languages.https://docs.swift.org/swift-book/LanguageGuide/Closures.html
クロージャは、コードの中で渡したり使用したりすることができる自己完結型の機能ブロックです。
Swiftのクロージャは、CやObjective-Cのブロックや他のプログラミング言語のラムダに似ています。クロージャの書き方
基本構文(全部盛り)
まずはこれをしっかりと覚えると、後に紹介する省略記法が理解しやすくなります。
{ (引数名1: 型, 引数名2: 型...) -> 戻り値の型 in 実行するコード... }例
// 定義 let intToString = { (a: Int, b: Int) -> String in return "\(a)と\(b)です" } // 利用する let sample1 = intToString(1, 5) print(sample1) // 1と5です省略
型表記
型が推論できるケースでは、引数や戻り値の型表記を省略できます。
- 型が推論できるケース
- 代入する変数の型が明確
- 関数の引数(関数定義で明確に記載される)
// 代入する変数の型が明確 var sample2: ((Int, Int) -> String) // 引数の()も省略可能 sample2 = { a, b in return "\(a)と\(b)です" } print(sample2(2, 3)) // 2と3ですreturn
クロージャ内の文がひとつしかない場合は
return
省略可能// return省略 let intToString = { (a: Int, b: Int) -> String in "\(a)と\(b)です" }下記コードはコンパイルエラーとなります。
// 2つ以上文があると省略不可 let sum = { (a: Int, b: Int) -> Int in let sum = a + b sum } // ;で1行にしてもダメ let sum = { (a: Int, b: Int) -> Int in let sum = a + b; sum }Shorthand Argument Names
型表記を省略できるケースでは、さらに引数名も省略可能です。
Shorthand Argument Names
は$
に引数のindexを合わせ、$0
や$1
と記載します。// 引数名も省略可能 // 型の表記も省略 -> in も省略しないとコンパイルエラー sample2 = { "\($0)と\($1)です" }
- 投稿日:2020-06-01T09:49:54+09:00
Stringで指定した文字数を抜き出す
Sample
var sampleText = "0123456789" let targetStart = sampleText.index(sampleText.startIndex, offsetBy: 2) let targetEnd = sampleText.index(sampleText.startIndex, offsetBy: 5) let substring = sampleText[targetStart...targetEnd] print(substring) // 2345Reference
- How can I use String slicing subscripts in Swift 4?
- Swift5で使える話
- #iOSDC でRangeとString.Indexについて話しました
- 少し古い話ではあるが、正しく詳しいので詳細はここを参照したい
Practice
- 前述の内容を基に、複数行のテキストを指定した行数に整形する関数を作りました。
- ただしWord Wrapは考慮していません。
import Cocoa /// テキストを指定した行数に整形する /// - Parameters: /// - text: 対象のテキスト /// - maxLineNumber: 整形したテキストの最大行数 /// - Returns: 最大行数以下に整形されたテキスト func createArrangedText(for text: String, maxLineNumber: Int) -> String { var lines = [String]() // 行ごとに分割する // また空行がある場合は削除する text.enumerateLines { (line, stop) -> () in let arranged_line = line.trimmingCharacters(in: NSCharacterSet.whitespacesAndNewlines) if arranged_line.count > 0 { lines.append(arranged_line) } } if maxLineNumber < lines.count && maxLineNumber > 0 { let oneLineText = lines.joined() lines = [] let numberOfCharacterByLine = oneLineText.count / maxLineNumber // 1行あたりの文字数 var targetStart = oneLineText.index(oneLineText.startIndex, offsetBy: 0) var targetEnd = oneLineText.index(oneLineText.startIndex, offsetBy: numberOfCharacterByLine) let targetVeryEnd = oneLineText.index(oneLineText.endIndex, offsetBy: 0) for i in 0..<maxLineNumber { let newLine: String if i == maxLineNumber - 1 { // 最終行は割り切れなかった字数文長くなる newLine = String(oneLineText[targetStart..<targetVeryEnd]) } else { newLine = String(oneLineText[targetStart..<targetEnd]) // 次のインデックス取得のために値を更新する targetStart = oneLineText.index(targetStart, offsetBy: numberOfCharacterByLine) targetEnd = oneLineText.index(targetEnd, offsetBy: numberOfCharacterByLine) } lines.append(newLine) } } return lines.joined(separator: "\r\n") } // from https://lipsum.sugutsukaeru.jp/index.cgi let inputText = """ ここは場合常にその相違式というのの後よりするないな。 どうしても結果をお話者はたとい大した鑑定なでなどを認めるが致したがも参考ありますですながら、どうには片づけませあっないた。 自分をおらで事もけっしてその間のまあなますな。 とにかく嘉納さんに忠告個性そう講演に聞いなくこの世その例外だれか享有にとかいうご教育たうですですば、 こういうたくさんも私か西洋底でいるて、大森さんののの人の私に何でもかでもお相当となっで私鶴嘴にご発展よりするようにせっかくお話が勤まりましでしと、 """ print(createArrangedText(for: inputText, maxLineNumber: 4)) /* ここは場合常にその相違式というのの後よりするないな。どうしても結果をお話者はたとい大した鑑定なでなどを認めるが致した がも参考ありますですながら、どうには片づけませあっないた。自分をおらで事もけっしてその間のまあなますな。とにかく嘉納 さんに忠告個性そう講演に聞いなくこの世その例外だれか享有にとかいうご教育たうですですば、こういうたくさんも私か西洋底 でいるて、大森さんののの人の私に何でもかでもお相当となっで私鶴嘴にご発展よりするようにせっかくお話が勤まりましでしと、 */
- 投稿日:2020-06-01T08:18:22+09:00
RealmSwiftで値が保存されない
はじめに
Realm Swiftを使っていてデータの保存がうまく出来ていなかったのですが
原因は単純なことだったので同じようにハマる人はいないかもしれませんが、念の為書き残しておきます。環境
Xcode: 11.3.1
Swift: 5
Realm Swift: 5.0.1間違っていたコード
class User: Object { dynamic var id = "" dynamic var name = "" } let user = User() user.id = "0001" user.name = "Test" let realm = try! Realm() try! realm.write() { realm.add(user) } let users = realm.objects(User.self) print(users.count) for u in users { print(u.id) print(u.name) }保存後に値を出力していますがレコードが追加されている(countがある)ことは確認できるものの
値は保存されておらず空文字が出力されていました。正しいコード
class User: Object { // 修正 @objc dynamic var id = "" @objc dynamic var name = "" } let user = User() user.id = "0001" user.name = "Test" let realm = try! Realm() try! realm.write() { realm.add(user) } let users = realm.objects(User.self) print(users.count) for u in users { print(u.id) print(u.name) }正しいコードはモデルクラスの変数に@objcが必要で
こちらを実行すると値が保存されていることが確認できました。おわりに
ちなみになぜ間違ったコードを書いていたかというと、
ググって出てきた最新のドキュメント(日本語版)を参考にしていましたが
このドキュメントがかなり古いバージョン(2.10.0)のもので
最新バージョンとの違いになかなか気づかなかったからでした。日本語版最新ドキュメント:https://realm.io/jp/docs/swift/latest/
英語版最新ドキュメント:https://realm.io/docs/swift/latest
- 投稿日:2020-06-01T07:11:05+09:00
UITableView セルのサイズを自動的に変更する
スタータープロジェクト
スタータープロジェクトでは、テーブルビューのセルに
UITextView
が一つだけあり、それには次のようなビューの制約(レイアウト)が含まれています:このプログラムビュー
Storyboard
では、テキストが表示されるはずです。しかしプログラムを実行しても画面には何も表示されません。テーブルビューのセルの高さが0になっているようです。
この記事ではこの問題の修正の仕方について学んでいきます。
問題を修正する
スクロールを無効化する
デフォルトでは
UITextView
はスクロールが有効になっています。固定した高さにするためにそれを無効化する必要があります。もともと、次のようなテーブルビューのクラスコードになっています。
class demoCell: UITableViewCell { @IBOutlet weak var textField: UITextView! }このコードを次のように更新します。
class demoCell: UITableViewCell { @IBOutlet weak var textField: UITextView! override func awakeFromNib() { super.awakeFromNib() textField.isScrollEnabled = false } }再びシミュレーターでプログラムを実行すれば、
UITextView
のコンテンツが正常に表示されているのがわかります。テキストの内容が変更された時にビューの高さを更新する。
UITextView
]内のテキストを編集しようとしても、テーブルビューのセルの高さは変わりません。しかし、高さは動的に変更する必要があります。自動で高さを設定する
テーブルビューのセルの高さを自動的に設定するようにシステムに指示することができます。
tableView.rowHeight = UITableView.automaticDimensionテキストの編集と連動させる
UITextViewDelegate
を設定して、テキストが変更されたときにイベントが連動するようにしますclass demoCell: UITableViewCell, UITextViewDelegate { @IBOutlet weak var textField: UITextView! override func awakeFromNib() { super.awakeFromNib() textField.isScrollEnabled = false textField.delegate = self } func textViewDidChange(_ textView: UITextView) { //新しいテキスト } }テキスト編集をテーブルビューコントローラに報告する
この変更を
UITableViewController
に報告すると、UITableViewController
がテーブルビューをリフレッシュしてセルの高さが更新されます。プロトコルを作成する
protocol demoCellDelegate : AnyObject { func textDidChange() }テーブルビューのセルで、
demoCellDelegate.textDidChange()
の関数を呼び出しますclass demoCell: UITableViewCell, UITextViewDelegate { @IBOutlet weak var textField: UITextView! weak var delegate: demoCellDelegate? override func awakeFromNib() { super.awakeFromNib() textField.isScrollEnabled = false textField.delegate = self } func textViewDidChange(_ textView: UITextView) { //新しいテキスト delegate?.textDidChange() } }そして、テーブルビューのクラスで、デリゲートを設定します:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "demo") as! demoCell cell.textField.text = "テスト テスト テスト テスト テスト テスト テスト テスト テスト テスト テスト" cell.delegate = self return cell }extension ViewController: demoCellDelegate { func textDidChange() { //TODO } }テーブルをリロードせずにテーブルビューを更新する
ここで、テーブルの高さを更新するために、
reloadData()
を使用しないでください。代わりにtableView.beginUpdates()
とtableView.endUpdates()
を使用してください。extension ViewController: demoCellDelegate { func textDidChange() { tableView.beginUpdates() tableView.endUpdates() } }そして、このプログラムをシミュレータで再度実行すると、次のようになります。
- 投稿日:2020-06-01T00:22:36+09:00
【Swift】2次元配列をCSVファイルに変換してUIActivityで共有したい!
2次元配列をCSVファイルに変換してえ!
2次元配列をユーザーに渡したい時ってあるよね?
あれ、、意外とない、、?今ぱっと考えたけど全然思いつかない?
とりまそういうこともたまにあるよね!
というわけで2次元配列をCSVに変換して、ついでにUIActivityで共有する方法までまとめてみました!!!!✨2次元配列 → CSV
まず2次元配列とファイル名を決める
ViewController.swiftvar fruitsArray : [[String]] = [["りんご","150円"],["みかん","120円"],["バナナ","180円"]] var fileName = "fruits"ボタンも作る!
ViewController.swift@IBAction func button(){ }2次元配列をCSVに変換!
Documentsの直下に配置しましょ!ViewController.swiftfunc createFile(fileName : String, fileArrData : [[String]]){ let filePath = NSHomeDirectory() + "/Documents/" + fileName + ".csv" print(filePath) var fileStrData:String = "" //StringのCSV用データを準備 for singleArray in fileArrData{ for singleString in singleArray{ fileStrData += "\"" + singleString + "\"" if singleString != singleArray[singleArray.count-1]{ fileStrData += "," } } fileStrData += "\n" } print(fileStrData) do{ try fileStrData.write(toFile: filePath, atomically: true, encoding: String.Encoding.utf8) print("Success to Wite the File") }catch let error as NSError{ print("Failure to Write File\n\(error)") } }CSV → UIActivity
共有するファイルをNSURLで指定して、UIActivityを設定!
ViewController.swiftlet shareFile = NSURL(fileURLWithPath: filePath) let activityItems = [shareFile] let activityVC = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) self.present(activityVC, animated: true, completion: nil)まとめ!
ViewController.swiftimport UIKit class ViewController: UIViewController { var fruitsArray : [[String]] = [["りんご","150円"],["みかん","120円"],["バナナ","180円"]] var fileName = "fruits" override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } @IBAction func button(){ createFile(fileName: fileName, fileArrData: fruitsArray) } func createFile(fileName : String, fileArrData : [[String]]){ let filePath = NSHomeDirectory() + "/Documents/" + fileName + ".csv" print(filePath) var fileStrData:String = "" //StringのCSV用データを準備 for singleArray in fileArrData{ for singleString in singleArray{ fileStrData += "\"" + singleString + "\"" if singleString != singleArray[singleArray.count-1]{ fileStrData += "," } } fileStrData += "\n" } print(fileStrData) do{ try fileStrData.write(toFile: filePath, atomically: true, encoding: String.Encoding.utf8) print("Success to Wite the File") }catch let error as NSError{ print("Failure to Write File\n\(error)") } let shareFile = NSURL(fileURLWithPath: filePath) let activityItems = [shareFile] let activityVC = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) self.present(activityVC, animated: true, completion: nil) } }引用元・参考元
http://begigrammer.hatenablog.com/entry/2017/01/01/041039
https://qiita.com/nashirox/items/56894599013d712faa0a
- 投稿日:2020-06-01T00:22:36+09:00
2次元配列をCSVファイルに変換してUIActivityで共有してえ!
2次元配列をCSVファイルに変換してえ!
2次元配列をユーザーに渡したい時ってあるよね?
あれ、、意外とない、、?今ぱっと考えたけど全然思いつかない()
とりまそういうこともたまにあるよね!というわけで2次元配列をCSVに変換して、ついでにUIActivityで共有する方法までまとめてみました!!!!2次元配列 → CSV
まず2次元配列とファイル名を決める
ViewController.swiftvar fruitsArray : [[String]] = [["りんご","150円"],["みかん","120円"],["バナナ","180円"]] var fileName = "fruits"ボタンも作る!
ViewController.swift@IBAction func button(){ }2次元配列をCSVに変換!
Documentsの直下に配置しましょ!ViewController.swiftfunc createFile(fileName : String, fileArrData : [[String]]){ let filePath = NSHomeDirectory() + "/Documents/" + fileName + ".csv" print(filePath) var fileStrData:String = "" //StringのCSV用データを準備 for singleArray in fileArrData{ for singleString in singleArray{ fileStrData += "\"" + singleString + "\"" if singleString != singleArray[singleArray.count-1]{ fileStrData += "," } } fileStrData += "\n" } print(fileStrData) do{ try fileStrData.write(toFile: filePath, atomically: true, encoding: String.Encoding.utf8) print("Success to Wite the File") }catch let error as NSError{ print("Failure to Write File\n\(error)") } }CSV → UIActivity
共有するファイルをNSURLで指定して、UIActivityを設定!
ViewController.swiftlet shareFile = NSURL(fileURLWithPath: filePath) let activityItems = [shareFile] let activityVC = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) self.present(activityVC, animated: true, completion: nil)まとめ!
ViewController.swiftimport UIKit class ViewController: UIViewController { var fruitsArray : [[String]] = [["りんご","150円"],["みかん","120円"],["バナナ","180円"]] var fileName = "fruits" override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } @IBAction func button(){ createFile(fileName: fileName, fileArrData: fruitsArray) } func createFile(fileName : String, fileArrData : [[String]]){ let filePath = NSHomeDirectory() + "/Documents/" + fileName + ".csv" print(filePath) var fileStrData:String = "" //StringのCSV用データを準備 for singleArray in fileArrData{ for singleString in singleArray{ fileStrData += "\"" + singleString + "\"" if singleString != singleArray[singleArray.count-1]{ fileStrData += "," } } fileStrData += "\n" } print(fileStrData) do{ try fileStrData.write(toFile: filePath, atomically: true, encoding: String.Encoding.utf8) print("Success to Wite the File") }catch let error as NSError{ print("Failure to Write File\n\(error)") } let shareFile = NSURL(fileURLWithPath: filePath) let activityItems = [shareFile] let activityVC = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) self.present(activityVC, animated: true, completion: nil) } }引用元・参考元
http://begigrammer.hatenablog.com/entry/2017/01/01/041039
https://qiita.com/nashirox/items/56894599013d712faa0a
- 投稿日:2020-06-01T00:22:36+09:00
2次元配列をCSVファイルに変換してUIActivityで共有したい!
2次元配列をCSVファイルに変換してえ!
2次元配列をユーザーに渡したい時ってあるよね?
あれ、、意外とない、、?今ぱっと考えたけど全然思いつかない?
とりまそういうこともたまにあるよね!
というわけで2次元配列をCSVに変換して、ついでにUIActivityで共有する方法までまとめてみました!!!!✨2次元配列 → CSV
まず2次元配列とファイル名を決める
ViewController.swiftvar fruitsArray : [[String]] = [["りんご","150円"],["みかん","120円"],["バナナ","180円"]] var fileName = "fruits"ボタンも作る!
ViewController.swift@IBAction func button(){ }2次元配列をCSVに変換!
Documentsの直下に配置しましょ!ViewController.swiftfunc createFile(fileName : String, fileArrData : [[String]]){ let filePath = NSHomeDirectory() + "/Documents/" + fileName + ".csv" print(filePath) var fileStrData:String = "" //StringのCSV用データを準備 for singleArray in fileArrData{ for singleString in singleArray{ fileStrData += "\"" + singleString + "\"" if singleString != singleArray[singleArray.count-1]{ fileStrData += "," } } fileStrData += "\n" } print(fileStrData) do{ try fileStrData.write(toFile: filePath, atomically: true, encoding: String.Encoding.utf8) print("Success to Wite the File") }catch let error as NSError{ print("Failure to Write File\n\(error)") } }CSV → UIActivity
共有するファイルをNSURLで指定して、UIActivityを設定!
ViewController.swiftlet shareFile = NSURL(fileURLWithPath: filePath) let activityItems = [shareFile] let activityVC = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) self.present(activityVC, animated: true, completion: nil)まとめ!
ViewController.swiftimport UIKit class ViewController: UIViewController { var fruitsArray : [[String]] = [["りんご","150円"],["みかん","120円"],["バナナ","180円"]] var fileName = "fruits" override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. } @IBAction func button(){ createFile(fileName: fileName, fileArrData: fruitsArray) } func createFile(fileName : String, fileArrData : [[String]]){ let filePath = NSHomeDirectory() + "/Documents/" + fileName + ".csv" print(filePath) var fileStrData:String = "" //StringのCSV用データを準備 for singleArray in fileArrData{ for singleString in singleArray{ fileStrData += "\"" + singleString + "\"" if singleString != singleArray[singleArray.count-1]{ fileStrData += "," } } fileStrData += "\n" } print(fileStrData) do{ try fileStrData.write(toFile: filePath, atomically: true, encoding: String.Encoding.utf8) print("Success to Wite the File") }catch let error as NSError{ print("Failure to Write File\n\(error)") } let shareFile = NSURL(fileURLWithPath: filePath) let activityItems = [shareFile] let activityVC = UIActivityViewController(activityItems: activityItems, applicationActivities: nil) self.present(activityVC, animated: true, completion: nil) } }引用元・参考元
http://begigrammer.hatenablog.com/entry/2017/01/01/041039
https://qiita.com/nashirox/items/56894599013d712faa0a
- 投稿日:2020-06-01T00:14:36+09:00
【Swift】Twitterの下から出てくるメニューを作りたい!!!(PanModal)
Twitterの下から出てくるメニュー!使いやすいよね
↑こんな感じでしたからニョキって出るやつ
実装してえ!!!???ライブラリを使って実装しよう
普通にライブラリなしでも作れるとは思うけど、やっぱりめんどくさいなーーーということで
それっぽいことができそうなライブラリを探してきたよ!?♂️
https://github.com/slackhq/PanModal
どっかでみたことあるなーって人いるでしょ?
「スッカカカ」でおなじみのSlackのライブラリなんですねーというわけでこいつを使ってTwitterみたいなニョキッとメニューを作ってくぞ!!!
作ろう!
1. ライブラリを入れよう
cocoapodsを使いますよー!
Podfileにこれを追記して pod installしてください!pod 'PanModal'2. ニョキっとさせるボタンを追加
お好みでButtonとかTableViewとかを置いてあげよう
これを押したときにニョキっとメニューが出るようなイメージ!
3. ニョキっとメニュー本体を作る
そんでとりまUITableViewDelegateとUITableViewDataSource、あとそれに関連したなんやかんやを書く!
(UITableViewでいいじゃんと思ったんですけど、なんかうまく動かなかったのでこうしてます 謎です)
次にニョキっとのキモを作ってくぞ!
PanModalをimportして、
もろもろ書こう!
これでニョキっとメニュー自体は完成!4. ニョキっとメニューを呼び出そう!
ニョキッとメニューを出したいタイミングで、
ViewController.swiftpresentPanModal(NyokittoViewController())5. 完成!
これでtwitterのメニューっぽいニョキっとメニューが完成!お疲れさまです〜〜〜〜〜〜
6. いろいろ改良してえ!
↑のやつだと問題点がいろいろあるから改良しようぜ!っていうやつです
なんかメニューがスクロールするんだけど
そういう時はこれを追記だ!
tableView.isScrollEnabled = falseこれを設定するとtableViewがスクロールしなくなるよ!便利だね!
ヘッダー欲しいんだけど
そういう時はヘッダーを作ろう!
let headerView:UIView = UIView() let label: UILabel = UILabel()ヘッダービューとそこに載せたいものを定義
これを追記
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { return headerView }override func viewDidLayoutSubviews() { label.text = "共有" label.textAlignment = .center label.textColor = .black label.font = UIFont.systemFont(ofSize: 14) label.frame = CGRect(x: 0, y: 0, width: headerView.frame.width, height: headerView.frame.height) headerView.addSubview(label) }あとheaderの高さを変えたい時は
tableView.sectionHeaderHeight = 40区切り線邪魔なんだけど
そういう時はこれを追記
tableView.separatorStyle = .noneメニュー押された時の動き書きたいんだけど
こう書く!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) //選択解除 /* ここになんやかんや書く */ }みんなもニョキっとメニュー作ろうぜ!
みんなもニョキっとメニュー作ろうぜ!
なんか結構付け焼刃なやり方だけど、ちょちょっと実装したい時とかに参考にしてみてください(絶対こんなのよりいいやり方ある、、、、、、)
GitHubもあげといたから参考にしてみて!
https://github.com/sugijotaro/NyokittoMenu参考
https://github.com/slackhq/PanModal
環境
Xcodeのバージョン:11.5
ライブラリ:PanModal
- 投稿日:2020-06-01T00:14:36+09:00
Twitterの下から出てくるメニューを作りたい!!!!!!(PanModalを使用)
Twitterのしたから出てくるメニュー!使いやすいよね
ライブラリを使って実装しよう
普通にライブラリなしでも作れるとは思うけど、やっぱりめんどくさいなーーーということで
それっぽいことができそうなライブラリを探してきたよ!
https://github.com/slackhq/PanModal
どっかでみたことあるなーって人いるでしょ?
「スッカカカ」でおなじみのSlackのライブラリなんですねーというわけでこいつを使ってTwitterみたいなニョキッとメニューを作ってくぞ!!!
作ろう!
1. ライブラリを入れよう
cocoapodsを使いますよー!
Podfileにこれを追記して pod installしてください!pod 'PanModal'2. ニョキっとさせるボタンを追加
お好みでButtonとかTableViewとかを置いてあげよう
これを押したときにニョキっとメニューが出るようなイメージ!
3. ニョキっとメニュー本体を作る
そんでとりまUITableViewDelegateとUITableViewDataSource、あとそれに関連したなんやかんやを書く!
(UITableViewでいいじゃんと思ったんですけど、なんかうまく動かなかったのでこうしてます 謎です)
次にニョキっとのキモを作ってくぞ!
PanModalをimportして、
もろもろ書こう!
これでニョキっとメニュー自体は完成!4. ニョキっとメニューを呼び出そう!
ニョキッとメニューを出したいタイミングで、
ViewController.swiftpresentPanModal(NyokittoViewController())5. 完成!
これでtwitterのメニューっぽいニョキっとメニューが完成!お疲れさまです〜〜〜〜〜〜
6. いろいろ改良してえ!
↑のやつだと問題点がいろいろあるから改良しようぜ!っていうやつです
なんかメニューがスクロールするんだけど
そういう時はこれを追記だ!
tableView.isScrollEnabled = falseこれを設定するとtableViewがスクロールしなくなるよ!便利だね!
ヘッダー欲しいんだけど
そういう時はヘッダーを作ろう!
let headerView:UIView = UIView() let label: UILabel = UILabel()ヘッダービューとそこに載せたいものを定義
これを追記
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { return headerView }override func viewDidLayoutSubviews() { label.text = "共有" label.textAlignment = .center label.textColor = .black label.font = UIFont.systemFont(ofSize: 14) label.frame = CGRect(x: 0, y: 0, width: headerView.frame.width, height: headerView.frame.height) headerView.addSubview(label) }あとheaderの高さを変えたい時は
tableView.sectionHeaderHeight = 40区切り線邪魔なんだけど
そういう時はこれを追記
tableView.separatorStyle = .noneメニュー押された時の動き書きたいんだけど
こう書く!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) //選択解除 /* ここになんやかんや書く */ }みんなもニョキっとメニュー作ろうぜ!
みんなもニョキっとメニュー作ろうぜ!
なんか結構付け焼刃なやり方だけど、ちょちょっと実装したい時とかに参考にしてみてください(絶対こんなのよりいいやり方ある、、、、、、)
GitHubもあげといたから参考にしてみて!
https://github.com/sugijotaro/NyokittoMenu参考
https://github.com/slackhq/PanModal
環境
Xcodeのバージョン:11.5
ライブラリ:PanModal
- 投稿日:2020-06-01T00:14:36+09:00
Twitterの下から出てくるメニューを作りたい!!!(PanModal)
Twitterのしたから出てくるメニュー!使いやすいよね
↑こんな感じでしたからニョキって出るやつ
実装してえ!!!???ライブラリを使って実装しよう
普通にライブラリなしでも作れるとは思うけど、やっぱりめんどくさいなーーーということで
それっぽいことができそうなライブラリを探してきたよ!?♂️
https://github.com/slackhq/PanModal
どっかでみたことあるなーって人いるでしょ?
「スッカカカ」でおなじみのSlackのライブラリなんですねーというわけでこいつを使ってTwitterみたいなニョキッとメニューを作ってくぞ!!!
作ろう!
1. ライブラリを入れよう
cocoapodsを使いますよー!
Podfileにこれを追記して pod installしてください!pod 'PanModal'2. ニョキっとさせるボタンを追加
お好みでButtonとかTableViewとかを置いてあげよう
これを押したときにニョキっとメニューが出るようなイメージ!
3. ニョキっとメニュー本体を作る
そんでとりまUITableViewDelegateとUITableViewDataSource、あとそれに関連したなんやかんやを書く!
(UITableViewでいいじゃんと思ったんですけど、なんかうまく動かなかったのでこうしてます 謎です)
次にニョキっとのキモを作ってくぞ!
PanModalをimportして、
もろもろ書こう!
これでニョキっとメニュー自体は完成!4. ニョキっとメニューを呼び出そう!
ニョキッとメニューを出したいタイミングで、
ViewController.swiftpresentPanModal(NyokittoViewController())5. 完成!
これでtwitterのメニューっぽいニョキっとメニューが完成!お疲れさまです〜〜〜〜〜〜
6. いろいろ改良してえ!
↑のやつだと問題点がいろいろあるから改良しようぜ!っていうやつです
なんかメニューがスクロールするんだけど
そういう時はこれを追記だ!
tableView.isScrollEnabled = falseこれを設定するとtableViewがスクロールしなくなるよ!便利だね!
ヘッダー欲しいんだけど
そういう時はヘッダーを作ろう!
let headerView:UIView = UIView() let label: UILabel = UILabel()ヘッダービューとそこに載せたいものを定義
これを追記
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? { return headerView }override func viewDidLayoutSubviews() { label.text = "共有" label.textAlignment = .center label.textColor = .black label.font = UIFont.systemFont(ofSize: 14) label.frame = CGRect(x: 0, y: 0, width: headerView.frame.width, height: headerView.frame.height) headerView.addSubview(label) }あとheaderの高さを変えたい時は
tableView.sectionHeaderHeight = 40区切り線邪魔なんだけど
そういう時はこれを追記
tableView.separatorStyle = .noneメニュー押された時の動き書きたいんだけど
こう書く!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { tableView.deselectRow(at: indexPath, animated: true) //選択解除 /* ここになんやかんや書く */ }みんなもニョキっとメニュー作ろうぜ!
みんなもニョキっとメニュー作ろうぜ!
なんか結構付け焼刃なやり方だけど、ちょちょっと実装したい時とかに参考にしてみてください(絶対こんなのよりいいやり方ある、、、、、、)
GitHubもあげといたから参考にしてみて!
https://github.com/sugijotaro/NyokittoMenu参考
https://github.com/slackhq/PanModal
環境
Xcodeのバージョン:11.5
ライブラリ:PanModal