struct ContentView: View { @State var isShow: Bool = false var body: some View { Button(action: { isShow = true }){ Text("シートを表示") } .sheet(isPresented: $isShow){ SomeView(isPresented: $isShow) } } } struct SomeView: View { @Binding var isPresented: Bool var body: some View { NavigationView { VStack { Image(systemName: "ladybug").scaleEffect(2.0) Text("Hello").font(.title2).padding() } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color(red: 0.9, green: 0.9, blue: 0.8)) .toolbar { ToolbarItem(placement: .navigationBarTrailing){ Button { isPresented = false } label: { Text("閉じる") } } } } } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() SomeView(isPresented: Binding.constant(false)) } }
Month: May 2022
[Swift] バイディングとオブジェクトの共有
@Binding, @Published, @ObservedObject, @StateObject, @EnvironmentObject
変数のバインディング、オブジェクトの共有を行う
### 変数を別のビューの変数と紐づけて使う
– 紐付けて使う変数を @Binding で宣言する
struct ContentView: View { @State var isChecked_person1: Bool = false var body: some View { HStack { Text("担当者1のチェック") PersonCheckMark(isChecked: $isChecked_person1) } } } struct PersonCheckMark: View { @Binding var isChecked: Bool var body: some View { Button(action: { isChecked.toggle() }) { Image(systemName: isChecked ? "person.fill.checkmark" : "person") .foregroundColor(isChecked ? .blue : .gray) .scaleEffect(2.0) .frame(width: 40, height: 40) } } }
### チェック担当者を2人に増やす
struct ContentView: View { @State var isChecked_person1: Bool = false @State var isChecked_person2: Bool = false var body: some View { VStack { HStack { Text("担当者1のチェック") PersonCheckMark(isChecked: $isChecked_person1) } HStack { Text("担当者2のチェック") PersonCheckMark(isChecked: $isChecked_person2) } Group { if isChecked_person1 && isChecked_person2 { Text("全員チェック済み").foregroundColor(.blue) } else { Text("チェック待ち").foregroundColor(.red) } } .font(.largeTitle) .padding(.top) } } }
ほう、
[Swift] タブやスワイプでビュー切り替え
struct ContentView: View { @State var selectedTag = 1 var body: some View { TabView(selection: $selectedTag){ Text("Tab Content 1").tabItem { Text("Tab Label 1")}.tag(1) Text("Tab Content 2").tabItem { Text("Tab Label 2")}.tag(2) Text("Tab Content 3").tabItem { Text("Tab Label 3")}.tag(3) } .font(.largeTitle) } }
### タブビューのビューを個別に宣言
struct ContentView: View { @State var selectedTag = 1 var body: some View { TabView(selection: $selectedTag){ HomeTabView().tabItem { Image(systemName: "house") Text("HOME") }.tag(1) WeatherTabView().tabItem { Image(systemName: "cloud.sun") Text("お天気") }.tag(2) NewsTabView().tabItem { Image(systemName: "newspaper") Text("ニュース") }.tag(3) } } } struct HomeTabView: View { var body: some View { VStack { Image(systemName: "music.note.house") .scaleEffect(x: 3.0, y: 3.0) .frame(width: 100, height: 100) Text("HOME").font(.system(size: 20)) } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color(red: 0.5, green: 0.9, blue: 0.9)) .ignoresSafeArea() } } struct WeatherTabView: View { var body: some View { VStack { Image(systemName: "cloud.sun") .scaleEffect(x: 3.0, y: 3.0) .frame(width: 100, height: 100) Text("お天気ページ").font(.system(size: 20)) } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color(red: 1.0, green: 0.9, blue: 1.0)) .ignoresSafeArea() } } struct NewsTabView: View { var body: some View { VStack { Image(systemName: "newspaper") .scaleEffect(x: 3.0, y: 3.0) .frame(width: 100, height: 100) Text("ニュースと解説").font(.system(size: 20)) } .frame(maxWidth: .infinity, maxHeight: .infinity) .background(Color(red: 0.9, green: 0.9, blue: 0.8)) .ignoresSafeArea() } } struct ContentView_Previews: PreviewProvider { static var previews: some View { ContentView() HomeTabView() WeatherTabView() NewsTabView() } }
TabViewの機能か、勉強になるね。
[Swift] グリッドレイアウト
LazyVGrid, LazyHGrid, GridItem, fixed, flexible, adaptive
struct ContentView: View { let grids = Array(repeating: GridItem(.fixed(80)), count:4) var body: some View { ScrollView() { LazyVGrid(columns: grids){ ForEach((1...100), id: \.self) { num in Page(str: String(num)) .cornerRadius(8) .frame(height: 60) } } } } }
グリッドのサイズ指定の3つのモード
– LazyVGrid(columns:grids)のグリッドレイアウトで何列並べるか、列幅はどうするかは配列gridsで決まる
GridItem(_size: GridItem.Size = .flexible(), spacing: CGFloat? = nil, alignment:Alignment? = nil)
struct ContentView: View { let grids = [GridItem(.fixed(30), spacing: 10, alignment: .center), GridItem(.fixed(50), spacing: 10), GridItem(.fixed(240))] var body: some View { LazyVGrid(columns: grids, alignment: .leading, spacing: 20){ ForEach(photoArray) { item in Image(systemName: "doc") Text(item.imageName).font(.caption) Text(item.title) } }.padding() } } struct PhotoData: Identifiable { var id = UUID() var imageName:String var title:String } var photoArray = [ PhotoData(imageName: "IMG_0463", title: "台風で流された親柱"), PhotoData(imageName: "IMG_0495", title: "横須賀ヴェルニー記念講演"), PhotoData(imageName: "IMG_1378", title: "恋人たちの湘南平テレビ塔"), PhotoData(imageName: "IMG_1739", title: "赤い漁具倉庫1"), PhotoData(imageName: "IMG_1742", title: "赤い漁具倉庫2"), PhotoData(imageName: "IMG_2233", title: "江ノ電501系"), PhotoData(imageName: "IMG_2406", title: "茅ヶ崎漁港引き上げモーター小屋"), PhotoData(imageName: "IMG_2407", title: "茅ヶ崎漁港第二えぼし丸"), PhotoData(imageName: "IMG_2864", title: "相模川河口調整水門"), PhotoData(imageName: "IMG_2909", title: "つくばエキスポセンター H2ロケット") ]
struct ContentView: View { let grids = [GridItem(.fixed(150), spacing: 20, alignment: .leading), GridItem(.fixed(20), spacing: 5, alignment: .leading), GridItem(.fixed(20), alignment: .leading)] var body: some View { ScrollView(.horizontal){ LazyHGrid(rows: grids, spacing:20){ ForEach(photoArray) { item in Image(item.imageName) .resizable() .aspectRatio(contentMode: .fit) .cornerRadius(8) Text(item.imageName).bold() Text(item.title).font(.caption) } }.padding() } } }
struct ContentView: View { let grids = [ GridItem(.adaptive(minimum: 80, maximum:.infinity)) ] var body: some View { ScrollView{ LazyVGrid(columns: grids, alignment: .leading, spacing: 10){ ForEach(1...100, id:\.self){ num in Ball(str: String(num)) .frame(width: 50, height: 50) } .padding() } } } } struct Ball: View { let str:String var body: some View { ZStack { Circle() .fill(Color.red) Text(str) .font(.title) .foregroundColor(.white) } } }
うおおおおおおお、なんか凄いことになってるな…
[Swift] 複数のビューをスクロール表示
ContentView.swift
struct ContentView: View { var body: some View { ScrollView { LazyVStack{ ForEach(0..<10) { num in Page(str: String(num)) .frame(width:200, height: 150) .cornerRadius(8) } } } .frame(width: 250, height: 500) .background(Color.gray.opacity(0.2)) } } struct Page: View { let colors:[Color] = [.green, .blue, .pink, .orange, .purple] let str:String var body: some View { ZStack { colors.randomElement() Text(str) .font(.largeTitle) .foregroundColor(.white) } } }
横スクロール
struct ContentView: View { let w:CGFloat = UIScreen.main.bounds.width-20 var body: some View { VStack(alignment: .leading){ Text("横スクロール").padding([.leading]) ScrollView(.horizontal){ LazyHStack(alignment: .center, spacing: 10){ ForEach(0..<10) { num in Page(str: String(num)) .frame(width: w, height: 150) .cornerRadius(8) } } } .frame(height: 200) .background(Color.gray.opacity(0.2)) } } }
LazyVStackとLazyHStackで見えてるところをスクロールさせるのね
なるほど、少しずつキャズムに足を踏み入れることが出来る様になってきた…
[Swift] スクロールビュー
ScrollView, LazyVStack, LazyHStack, UIScreen.main.bounds, ForEach-in
PhotoData.swift
import Foundation struct PhotoData: Identifiable { var id = UUID() var imageName:String var title:String } var photoArray = [ PhotoData(imageName: "IMG_0463", title: "台風で流された親柱"), PhotoData(imageName: "IMG_0495", title: "横須賀ヴェルニー記念講演"), PhotoData(imageName: "IMG_1378", title: "恋人たちの湘南平テレビ塔"), PhotoData(imageName: "IMG_1739", title: "赤い漁具倉庫1"), PhotoData(imageName: "IMG_1742", title: "赤い漁具倉庫2"), PhotoData(imageName: "IMG_2233", title: "江ノ電501系"), PhotoData(imageName: "IMG_2406", title: "茅ヶ崎漁港引き上げモーター小屋"), PhotoData(imageName: "IMG_2407", title: "茅ヶ崎漁港第二えぼし丸"), PhotoData(imageName: "IMG_2864", title: "相模川河口調整水門"), PhotoData(imageName: "IMG_2909", title: "つくばエキスポセンター H2ロケット") ]
PhotoView.swift
import SwiftUI struct PhotoView: View { var photo:PhotoData var body: some View { VStack { Image(photo.imageName) .resizable() .aspectRatio(contentMode: .fit) Text(photo.title) .bold() .padding(.top, 10) .padding(.bottom, 20) } .background(Color(red: 0.3, green: 0.8, blue: 0.5)) .cornerRadius(8) } } struct PhotoView_Previews: PreviewProvider { static var previews: some View { PhotoView(photo:photoArray[0]) } }
写真データを取り込んでスクロール表示する
struct ContentView: View { var body: some View { ScrollView { LazyVStack(alignment: .center, spacing: 20){ ForEach(photoArray) { photoData in PhotoView(photo:photoData) } } }.padding(.horizontal) } }
うおおおおおおおおお
これは凄いな
[Swift] ハーフモーダルビュー
struct ContentView: View { @State var isModal: Bool = false var body: some View { Button(action: { isModal = true }) { Text("Sheet テスト") } .sheet(isPresented: $isModal){ SomeView() } } }
struct ContentView: View { @State var isModal: Bool = false @State var counter:Int = 0 var body: some View { VStack { Button(action: { isModal = true }) { Text("Sheetテスト") } .sheet(isPresented: $isModal, onDismiss: {countUp(}){ SomeView() } .disabled(counter >= 3) Text("回数\(counter)") .font(.title) .paddin() } } func countUp(){ counter += 1 } }
なんか久しぶりにSwift触ると、全然頭がついていけないな
少しずつでも毎日継続してやらないと駄目だ
[Linux] evalとは
文字列を評価、連結して実行する
hoge.txt
hoge hoge
fuga.txt
fuga fuga fuga
example.sh
#!/bin/bash value='hoge' #文字列としてコマンドを変数に格納 cmd='grep $value hoge.txt' echo $cmd eval $cmd
$ sh example.sh
grep $value hoge.txt
hoge hoge
#!/bin/bash grep_text() { for txt_file in $(ls . | grep ".txt$"); do grep_result=$(grep $1 $txt_file) if [ $? -eq 0 ]; then eval echo $2 fi done } query='hoge' message='検索対象が見つかりました。見つかったファイル名:$txt_file' grep_text $query "${message}" query='fuga' message='検索対象が見つかりました。見つかったファイル名:$grep_result' grep_text $query "${message}"
$ sh success.sh
検索対象が見つかりました。見つかったファイル名:hoge.txt
検索対象が見つかりました。見つかったファイル名:fuga fuga fuga
何これ、やればやるほど次から次へと課題が出てくる
sedコマンド
文字列を全置換したり行単位で抽出したり、削除したり、テキスト処理できるコマンド
コマンドラインパラメータで指定して非対話的に一括処理もできる
sedはStream EDitorの略
### sedの構文
sed OPTIONS… [SCRIPT] [INPUTFILE…]
[SCRIPT]とは “s/foo/bar/g”
“-e”オプションで直後に[SCRIPT]が来る
$ echo “Tech Blog” | sed -e “s/Blog/Comment/g”
Tech Comment
$ echo “Tech Blog” | sed -e “s/ /-/g”
Tech-Blog
バックスラッシュはエスケープ
$ echo “Tech Blog” | sed -e “s/ /\!/”
Tech!Blog
二つ目に見つかった”o”を”_”に変換
$ echo “Hello World” | sed -e “s/o/__/2”
Hello W__rld
### ファイルの書き換え
$ echo “Hello World” > sample.txt
$ sed -e “s/World/Coffee/g” sample.txt
Hello Coffee
$ cat sample.txt
Hello World
$ sed -i -e “s/World/Shinbashi/g” sample.txt
$ cat sample.txt
Hello Shinbashi
他にも色々使い方ができる
取り敢えず置換ができると覚えておく
GitLab CIを活用
.gitlab-ci.yml
stages: - npm - composer - upload npm: stage: npm image: node:12.14.1-alpine3.111 script: - npm install - npm audit fix - npm run production - tar czf node_modules.tar.gz node_modules artifacts: paths: - node_modules.tar.gz composer: stage: composer image: composer:1.9 script: - composer install - zip -r ./${CI_PIPELINE_ID}.zip . artifacts: paths: - ./${CI_PIPELINE_ID}.zip s3upload: stage: upload image: alpine:latest before_script: - apk add --no-cache python3 - pip3 install awscli script: - aws s3 cp ./${CI_PIPELINE_ID}.zip s3://${S3BUCKET}/${APP}.zip
build: stage: build script: - echo compile and package - echo tag image version - branch_name=$(echo $CI_COMMIT_REF_NAME | sed 's/\//-/g') - version="$branch_name-$CI_PIPELINE_ID" - echo login ECR and push image - eval $(aws ecr get-login --no-include-email --region ap-northeast-1) - docker tag app:latest myimage:${version} - docker push myimage:${version} only: refs: - feature - develop - integration - hotfix - master changes: - src/*/* tags: - build-runner deploy: stage: deploy script: - echo "Deploy app" - branch_name=$(echo $CI_COMMIT_REF_NAME | sed sed 's/\//-/g') - version="$branch_name-$CI_PIPELINE_ID" - echo $version > codedeploy/image_version.txt - cd codedeploy - zip -r deploy.zip appspec.yml image_version.txt scripts - aws s3 cp deploy.zip s3://codedeploy/automation/${CI_COMMIT_REF_NAME}/app/deploy.zip --metadata x-amz-meta-application-name=app,x-amz-meta-deploymentgroup-name=${obj} only: refs: - feature - develop - integration - hotfix - master changes: - src/**/* tags: - deploy-runner
install.sh
#!/bin/bash # Script is run on instance # Get app version dir=$(dirname "$0") version=$(cat ${dir}/../image_version.txt) # Tracking version OPS_DIR="/ect/ops" export APP_VERSION=${version} # Compose up docker-compose up -d app
appspec.yml
version: 0.0 os: linux hooks: BeforeInstall: - location: scripts/install.sh timeout: 300 runas: root