20200522のSwiftに関する記事は6件です。

Swiftの文について見ていきます

概要

新たにSwiftを学び始めたので、アウトプットも兼ねて、Xcodeの文を見ていきます。

viewController.swift
class ViewController: UIViewController {
    @IBOutlet weak var countLabel: UILabel!
    var count = 0 
    override func viewDidLoad() {
        super.viewDidLoad()
        countLabel.text = "0" 
    }
    @IBAction func plus(_ sender: Any) {
        count = count + 1     
        countLabel.text = String(count)
        if(count >= 10){
            changeTextColor()
        }
    }
    @IBAction func minus(_ sender: Any) {
        count = count - 1
        countLabel.text = String(count)
        if(count <= 0){
            resetColor()
        }
    }
    func changeTextColor(){
        countLabel.textColor = .yellow
    }
    func resetColor(){
        countLabel.textColor = .white
    }
}

class ViewController: UIViewController {

    @IBOutlet weak var countLabel: UILabel!
    var count = 0 

この部分は変数の宣言になります。varとつけて宣言を表明し、その後にcountLabelという変数名をつけています。その後のcount変数を宣言して 0 を代入しています。

    override func viewDidLoad() {
        super.viewDidLoad()
        countLabel.text = "0" 
    }

この部分はアプリを開いた時に自動的に読み込まれる箇所です。
countLabelにオブジェクト.textをつけてそれに文字型の0を代入して表示しています。

    @IBAction func plus(_ sender: Any) {
        count = count + 1     
        countLabel.text = String(count)
        if(count >= 10){
            changeTextColor()
        }
    }

この部分はボタンがタッチされた時該当する plusメソッドが動きますが、その処理を記述しています。
countに1を足す処理です。そしてさらに足したcountを文字型に変えて表示しています。
その後のif文はcountが10超えたらchageTextColorというメソッドを読み込むという記述です。

    @IBAction func minus(_ sender: Any) {
        count = count - 1
        countLabel.text = String(count)
        if(count <= 0){
            resetColor()
        }
    }

ここはさっきと逆でcountから1引く処理をしています。そしてそれを文字型に変えて表示。if文で0以下になったらresetColorというメソッドが読み込まれるという記述です。

    func changeTextColor(){
        countLabel.textColor = .yellow
    }
    func resetColor(){
        countLabel.textColor = .white
    }

最後にこの箇所はメソッドを定義する箇所です。
changeTextColorメソッドでは.textColorオブジェクトを使って文字を黄色に変えています。
resetColorメソッドは同じように文字を白色に変えています。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

GCDを使ってコールバック地獄をasync/await ライクに回避する

⚠️ 注意 ⚠️

こちらの記事は何かを参考にして書いたというよりもSwift実践入門のGCDの項を読んで自分で編み出した部分が強いので、誤っている可能性があります。

もし強いSwiftエンジニアの方

  • ここは間違っている
  • もっといいやり方があるよー

などありましたら、コメントで教えていただけると幸いです :bow:

いわゆるコールバック地獄

Swiftである非同期処理の結果を別の非同期処理に渡して処理をチェーンさせたい場合、以下のようにコールバックを使うのがよくやるやり方です。

func main() {
    funcOne { funcOneResult in
        print(funcOneResult)
    }
}

func funcOne(callback: @escaping (_ result: String) -> Void) {
    let globalQueue = DispatchQueue.global(qos: .userInitiated)
    globalQueue.async {
        print("func one called")
        Thread.sleep(forTimeInterval: 1)
        callback("funcOneResult")
    }
}

上記のように1つなら全然問題ありませんが、2つ、3つとチェーンさせていくと、悪名高いコールバック地獄が発生します。

import Foundation
import Dispatch

let globalQueue = DispatchQueue.global(qos: .userInitiated)

func main() {
    funcOne { funcOneResult in
        funcTwo(funcOneResult: funcOneResult) { funcTwoResult in
            funcThree(funcTwoResult: funcTwoResult) { funcThreeResult in
                print("result: \(funcThreeResult)")
            }
        }
    }
}

話は変わってjavascriptではasync/awaitを用いて、このようなコールバック地獄を回避することができます。
イメージこんな感じです。

async function main() {
  const resultOne = await funcOne()
  const resultTwo = await funcTwo(resultOne)
  const resultThree = await funcThree(resultThree)
  console.log(resultThree)
}

Swiftでもこんな風に実装したいなと思い、紹介するのが今回の方法です。

GCDを使って async/await likeに回避

GCD(Grand Central Dispatch)はC言語ベースのシステムレベルのAPIでキューを通してスレッドの管理を容易にする仕組みで本来は非同期処理に用いるものですが、今回はこちらを同期処理に用います。
ソース全体は以下です。
メソッド呼び出しの箇所のコールバック地獄が取り除かれ、先ほどのjavascriptライクに書けているのが分かります。

import Foundation
import Dispatch

func main() {
    let queue = DispatchQueue(label: "com.my_company.app", qos: .userInteractive, attributes: [.concurrent])
    let funcOneResult = funcOne(queue: queue)
    let funcTwoResult = funcTwo(funcOneResult: funcOneResult, queue: queue)
    let funcThreeResult = funcThree(funcTwoResult: funcTwoResult, queue: queue)
    queue.sync {
        print("completed, result: \(funcThreeResult)")
    }
}

func funcOne(queue: DispatchQueue) -> String {
    queue.sync {
        print("func one called")
        Thread.sleep(forTimeInterval: 1)
        return "funcOneResult"
    }
}

func funcTwo(funcOneResult: String, queue: DispatchQueue) -> String {
    queue.sync {
        print("func two called")
        Thread.sleep(forTimeInterval: 1)
        return "funcTwoResult"
    }
}

func funcThree(funcTwoResult: String, queue: DispatchQueue) -> String {
    queue.sync {
        print("func three called")
        Thread.sleep(forTimeInterval: 1)
        return "funcThreeResult"
    }
}

main()

仕組みとしては直列キューを作成して各メソッドの呼び出しの引数として呼び出し、

let queue = DispatchQueue(label: "com.my_company.app", qos: .userInteractive, attributes: [.concurrent])
let funcOneResult = funcOne(queue: queue)
let funcTwoResult = funcTwo(funcOneResult: funcOneResult, queue: queue)
let funcThreeResult = funcThree(funcTwoResult: funcTwoResult, queue: queue)

メソッド内で、そのqueueに対して、syncで処理を呼び出しています。

func funcOne(queue: DispatchQueue) -> String {
    queue.sync {
        print("func one called")
        Thread.sleep(forTimeInterval: 1)
        return "funcOneResult"
    }
}

こうすることで処理が同期的に進行し、以下のような出力となります。

func one called
(1秒)
func two called
(1秒)
func three called
completed, result: funcThreeResult

エラーのハンドリングを行う場合は以下のようになるのではないかなと思います。

func main() {
    let queue = DispatchQueue(label: "com.my_company.app", qos: .userInteractive, attributes: [.concurrent])
    do {
        let funcOneResult = try funcOne(queue: queue)
        let funcTwoResult = try funcTwo(funcOneResult: funcOneResult, queue: queue)
        let funcThreeResult = try funcThree(funcTwoResult: funcTwoResult, queue: queue)
        queue.sync {
            print("completed, result: \(funcThreeResult)")
        }
    } catch {
        // handle error
        print(error)
    }
}

extension String: Error {}
func funcOne(queue: DispatchQueue) throws -> String {
    try queue.sync {
        print("func one called")
        throw "Some Error"
        Thread.sleep(forTimeInterval: 1)
        return "funcOneResult"
    }
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【iOS】iOSアプリ開発入門~ Swift基礎編1~

前回はボタンタップイベントを受けラベルの色を変更する方法について投稿しました。
SwiftとUIの接続編1:https://qiita.com/euJcIKfcqwnzDui/items/93f010b989a4d333f0b9

今回はいくつか簡単な処理を紹介します。
Swiftのコーディング練習がてらこのあたりの処理を入れてもう少しアプリらしくしてみましょう。
それではいつも通りプロジェクトを開いて実装していきましょう。

カウントアップさせる処理

ボタンをタップする毎に表示される数字が増えるような処理を紹介します。

デバッグコンソールにカウントアップを表示する

まずカウントアップさせるには今いくつまでカウントされているかという状態を保持しておく必要があります。
この状態を保持するためのスペースをプロパティに準備しておきます。
以下のようにコードを編集します。

ViewController.swift
class ViewController: UIViewController {
    var count: Int = 0  // < 追加
    @IBOutlet weak var label: UILabel!

    @IBAction func tapButton(_ sender: Any) {
        self.label.text = "Hello World"
        self.label.backgroundColor = UIColor.red
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }
}

countというプロパティをInt型で定義しました。
Intは整数型と呼ばれるものです。数字、特に整数で扱うものはInt型で定義します。

一部例外はありますがプログラムでは型を意識する必要があります。
整数ならInt型、少数ならDouble型、文字列ならString型というようにそれぞれ用途に合わせて型を指定してあげなければいけません。
今回の場合はボタンをタップする毎に数字を1ずつ増やすという処理をしたいのでInt型として定義しました。

var count: Int = 0というように定義していますが、この= 0いうのは初期化処理です。
つまりcountの初期値は0という値ですよとしてあげています。

それではこのcountを使って実装していきます。

tapButtonの処理を以下のように書換えてみます。
書換えたら実行してボタンを何度かタップしてみてください。

ViewController.swift
    @IBAction func tapButton(_ sender: Any) {
        print("加算前:\(self.count)")
        self.count = self.count + 1
        print("加算後:\(self.count)")
        print("-----")
    }

デバッグコンソールに以下のように出力されました。
print()関数に関しては以前しました。デバッグコンソールに出力するための処理です。

加算前:0
加算後:1
-----
加算前:1
加算後:2
-----
加算前:2
加算後:3
-----

見ればなんとなくわかるかもしれませんが、ボタンをタップする度にself.count = self.count + 1という処理でcountの値に1を加算しています。

ここで出てきた=や+は演算子またはオペレータと呼ばれます。
プログラミングではこの演算子を使い計算をしていきます。

「+」はそのままの意味で足し算を行います。
少し注意が必要なのは「=」で、こちらは代入演算子と呼ばれています。
数学上の意味では「=」は等価、つまり左辺と右辺の関係式を表しますがプログラム上では代入を意味します。
少しニュアンスが難しいかも知れませんがここの処理はself.count + 1の計算結果をself.countに代入しています。その結果self.countの値が1加算されたものに書き換わります。
(ちなみに等価の演算子は「==」です)

一回目のタップでは代入される前のself.countの初期値は0のためprint("加算前:\(self.count)")では「0」が表示され、加算後self.countの値は1に書き換わったためprint("加算後:\(self.count)")では「1」が表示されています。

二回目のタップではself.countの値は一回目に1に書換えているためprint("加算前:\(self.count)")では「1」が表示され、さらに書き換えを行い2に更新しています。

試しに代入を行わず以下のような処理にしてみましょう。

ViewController.swift
    @IBAction func tapButton(_ sender: Any) {
        print("加算前:\(self.count)")
        print("加算後:\(self.count + 1)")
        print("-----")
    }

以下のように出力されました。

加算前:0
加算後:1
-----
加算前:0
加算後:1
-----
加算前:0
加算後:1
-----

これはself.countに代入を行っていないため初期値の0のままになっているためです。
self.count + 1の計算はprint("加算後:\(self.count + 1)")で1と表示されているので正しく行われていますが、self.countが更新されないため同じ結果が常に表示されています。
値を更新したい場合は必ず代入するようにしてください。

このようにして値を更新、保持しながらアプリの状態を制御していきます。

カウントアップ結果をラベルに表示する

print()関数だけではアプリの表示は変更されないのでself.countを表示してみましょう。
これまでの内容を理解できていれば特に難しいことはなく、ラベルの表示変更とカウントアップの処理を組み合わせるだけです。

コードを以下の様に書き換え実行してみましょう。

ViewController.swift
    @IBAction func tapButton(_ sender: Any) {
        self.count = self.count + 1
        self.label.text = "カウント:\(self.count)"
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.label.text = "カウント:\(self.count)"
    }

ラベルの表示が「カウント:0」から始まり、ボタンをタップする毎にカウントが増えていきました。
基本的には前項の処理とは変わらずself.count = self.count + 1で1ずつ加算していき、その値をラベルに表示しているだけです。

処理をもう少し詳しく見ててみましょう。

まずtapButton内の処理について。
先程と同様にself.count = self.count + 1self.countが更新されていますね。
更新した結果をself.label.text = "カウント:\(self.count)"に代入しています。
そのためラベルには加算された値が表示されています。
ラベルの更新の際self.count\()で囲まれています。
冒頭で言いましたがプログラムでは型を意識する必要があります。
UILabelのtextの定義を見てみます。(見方は前回説明しました)

open var text: String?というように定義されています。
「?」はひとまず気にせず、String型つまり文字列型で定義されており、countInt型なので型が異なるということがわかります。
プログラムでは型が異なる場合は直接代入できないという決まりがあります。
そこでIntStringに変換してあげる必要があります。
型を変換する処理のことをキャストと呼び、\()IntStringにキャストするための処理です。
キャストしてあげた結果"カウント:\(self.count)"String型に変換されtextに代入できるようになりました。

次はviewDidLoadの処理について。
tapButtonの処理では更新した値を表示していますが、1を加算した値を表示しているため初期値の0が表示されることはありません。
そもそもtapButtonはボタンをタップするというイベントを起こして初めて動く処理のため、画面を表示した瞬間のラベルの表示を制御できません。
ですがアプリを実行したときは「カウント:0」と表示されていました。
これを実現するための処理がviewDidLoadの内容です。
このviewDidLoadはプロジェクトを作成した段階ですでに定義されていましたが、何をするための処理なんでしょう?
今回は詳しく説明しませんがアプリの画面、つまりViewControllerにはライフサイクルというものがあり、「画面が表示された」、「画面が非表示」になったなど、画面の表示状態などによって勝手に呼ばれるメソッドが元々定義されています。
viewDidLoadもライフサイクルの1つで「画面がメモリ上に確保された」タイミングで呼ばれます。
基本的にこのタイミングで画面の初期化処理を行います。
初期化処理としてself.label.text = "カウント:\(self.count)"を行ったため画面が表示された瞬間「カウント:0」と表示されていたというわけです。

カウント毎にテキストの色を変える

もう少し遊んでみましょう。
先程等価式は「==」の演算子を使うと少し話しましたがこの等価演算子を使ってみます。

プログラムには条件判定を行うためにif文を呼ばれるものが用意されています。EXCELなどにもありますがそれと同じです。
「if文」を使えば特定の条件の場合のみ行う処理を記述することができます。

コードを以下の様に書き換え実行してみましょう。

ViewController.swift
    @IBAction func tapButton(_ sender: Any) {
        self.count = self.count + 1
        self.label.text = "カウント:\(self.count)"

        let remainder: Int = self.count % 2
        if remainder == 0 {
            self.label.textColor = UIColor.red
        } else {
            self.label.textColor = UIColor.blue
        }
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        self.label.textColor = UIColor.red
        self.label.text = "カウント:\(self.count)"
    }

タップする度に文字色が赤→青→...と変わります。

viewDidLoadで文字色の初期値を赤に指定していますね。
tapButtonに注目してください。
let remainder = self.count % 2とあります。
まず「%」は余りを求める演算子です。self.count % 2self.countを2で割った余りを結果として返します。
つまり偶数の場合は0、奇数の場合は1となり、remainderには0 ro 1が代入されます。

remainder == 0ではremainderと0が等価かどうかを計算しています。
このように「==」など左右の値の関係を比較する演算子を比較演算子と呼びます。
比較演算子は他に「>」,「>=」,「<」,「<=」があります。これらの意味は数学と同じで大なり、大なりイコールといった意味になります。
比較演算子の計算結果はInt型ではなくBool型となります。Bool型は論理型と呼ばれ真偽値、つまりtrue/falseを格納します。
今回の場合0と比較しているのでremainderが0ならtrue、1ならfalseの値が返されます。
試しにprint(remainder == 0)とするとtrue or falseが表示されます。

「if文」では真偽値を判定します。
構文としては以下の様になります。

if 真偽値 {
    trueの場合の処理
} else {
    falseの場合の処理
}

従ってcountが偶数の場合は文字色が赤となり、奇数の場合は文字色が青となったというわけです。

余談ですがif文は以下のような感じでelseなしやさらにif文で繋げることもできます。

// else なし
if self.count % 2 == 0 {
    // countが「2n」の場合の処理
}

// if文を繋げる
if self.count % 3 == 0 {
    // countが「3n」の場合の処理
} else if self.count % 3 == 1 {
    // countが「3n+1」の場合の処理
} else {
    // 上記判定に当てはまらなかった場合の処理
}

最後に

今回はカウントアップや条件分岐など少しプログラミング的な処理を入れてUIを更新してみました。
もちろんこれは簡単な例でさらに複雑な処理を与えてあげればもっと細かい制御ができるようになります。

今回紹介した内容は簡単ではありますが全てのプログラミングに共通する考え方で非常に重要な内容です。
もし理解できなかった場合は読み直しさらに練習するなどで自分のものにしてください。

特にif文は非常に重要で、他に繰り返しを制御するfor文というものがありますが
if文とfor文があれば全ての処理を記述できると言われています。
しっかりと理解できるようにしましょう。

for文という単語を出したので次回はfor文を使ってUIを更新してみたいと思います。

本連載ではプログラミング未経験からiOSアプリ開発が行えるようになることを目的としています。
今までの投稿をまとめていますのでこちらもご覧ください。
アジェンダ:https://qiita.com/euJcIKfcqwnzDui/items/0b480e96166e88945684

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【swift】singleton(シングルトン)とその代替案について

はじめに

今回は、シングルトンについて書いていこうと思います!
シングルトンとはなんぞやと言うところから、シングルトンを使う場面やメリットについて公式ドキュメントを元に書いていきます!

公式doc:Managing a Shared Resource Using a Singleton

共有リソースの管理者:シングルトン

公式ドキュメントのタイトルにある通り、シングルトンは共有リソースにアクセスします。
ざっくり言えば、インスタンス内の値を変更後、別のインスタンスを生成しても前者のインスタンスの更新内容が反映されるどういった処理が可能になります。

つまり、インスタンスが1個しか生成されないことを保証します。

イメージとしては、こちらの記事がとても参考になるので一読をお勧めします!
シングルトンについて swift

まず、コードでみていきます!

class single {
    var name = "singletonのお勉強"
    static let singleton = single()  //staticキーワードでsingle()をsingletonに代入
    private init(){}
}

var test = single.singleton  //最初のインスタンス
print(test.name)  //出力:singletonのお勉強
test.name = "singleton実装"

let singleton = single.singleton  //値更新後のインスタンス
print(singleton.name)  //出力:singleton実装

見ての通り、static let singleton = single() の部分でsingletonを作ります。
そうすることで、複数のスレッドで同時アクセスされた場合でも、1回だけ遅延して初期化されることが保証されます。

また、初期化以外の設定を実行する必要がある場合は、以下のようにクロージャーを用いることもあります。

class singleton{
  static let sharedInstance: singleton = {
    let instance = singleton()
    //追加設定処理
    return instance
   }()
}

シングルトンの使う場面

この機能についてはおおよそわかったが、では一体どのような場面でシングルトンを使うのだろうか、、

Swift におけるシングルトン・staticメソッドとの付き合い方

こちらの記事によると、

  • delegateにシングルトンインスタンスしか渡せない場合
  • インスタンスメソッド実装が必要な既存のプロトコルに準拠させたい場合
  • その他、大体の場合staticプロパティ・メソッドを束ねたstructで代用できる

え、singleton使う場面、めっちゃ少ないやん

この記事の筆者曰く、swiftの場合、singletonの実装が簡単なので必要なくても使ってもいいのではと。

シングルトンは大抵、staticプロパティ・メソッドを束ねたstructで代用できる

実際にコードで見ていきます


struct MyStruct{
  private init(){}
  static var value = "original"
  static func foo() { print("foo") }
}

var myStruct = MyStruct.self
myStruct.foo()

myStruct.value = "シングルトンもどき"
print(myStruct.value)  // シングルトンもどき
print(MyStruct.value)  // シングルトンもどき

確かに、、シングルトンと同じだ、、

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Core Data を使用する既存のアプリに CloudKit 機能を追加

Core Data テクノロジーを使用するアプリをお持ちの場合は、CloudKit サポートを簡単に追加できます。

CloudKit を利用すれば、データベースに保存されたデータをユーザーのデバイス間で同期させることができます。

CoreData + CloudKit 機能は、デフォルトで、ユーザーの情報をプライベートデータベースに保存します。つまり、ユーザーが他のデバイス上で同じApple IDを使ってサインインした場合にのみ保存されたユーザーの情報にアクセスできます。

ステップ 1. Xcodeプロジェクト設定で必要な機能をオンにする。“iCloud”の"CloudKit”をオンにする。

image.png

「CloudKit」をオンにします

image.png

既存の"Containers"のトグルボタンをどれかひとつクリックするか、プラスアイコンをクリックして新規"Container"を加える。

新規"Container"を加える:

追加ボタンをクリックします

68747470733a2f2f71696974612d696d6167652d73746f72652e73332e61702d6e6f727468656173742d312e616d617a6f6e6177732e636f6d2f302f3633353333302f39613239373166332d623134392d343962622d656466332d3661646132313237623962392e706e67.png

新しい「Container」の名前を入力してください

Screen Shot 2020-05-12 at 1.06.19 PM.png

ステップ 2. Core Data の設定で CloudKit サポートをオンにします

データベースモデルを変更

  1. まず、. xcdatamodeld ファイルを開きます
  2. Configuration タブで構成を選択します:

Screen Shot 2020-05-21 at 16.28.11.png

  1. 画面の右側で、クリックし、CloudKit で使用をオンにします (Used with CloudKit)

Screen Shot 2020-05-21 at 16.29.37.png

コード内のクラウドコンテナにアクセスする

そして、すべてのNSPersistentContainerNSPersistentCloudKitContainerに置き換えます。AppDelegate.swiftファイルに1つある可能性があります。

元の:

let container = NSPersistentContainer(name: "CoreDataDemo")

新:

let container = NSPersistentCloudKitContainer(name: "CoreDataDemo")

ステップ 3. テストとデプロイ

  1. クラウドデータベースを設定する必要がないことに注意してください。データベース構造は自動的に CloudKit の開発サーバーにデプロイされます。次に、しばらくの間アプリを使用し、Core Data データが生成されていることを確認する必要があります。

  2. このステップは重要です!次にCloudKitのオンラインポータル http://icloud.developer.apple.com へ行き、あなたのアプリを左側から見つけて、開発データベースをプロダクションにデプロイします。これを忘れると、App Storeからあなたのアプリをダウンロードした実際のユーザーが、データをクラウドに同期できなくなります。

最後にはiCloudの開発用データベースを本番環境にデプロイする必要があります。

Screen Shot 2020-05-11 at 4.32.00 PM.png

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

【SwiftUI】基本的なモディファイアの種類と使い方①

bodyプロパティ

定義:var body: Self.Body
ContentViewではカスタムビューの内容を記述する
複数のViewを組み合わせるにはVStackなどを使用してひとつにまとめる必要がある。

frameモディファイア

フレームのサイズとビューの配置位置を指定

func frame(width: ,height: , alignment: ,)
alignmentの種類
center,leading,trailing,top,bottom,topLeading,topTrailing,bottomLeading,bottomTrailing
func frame(minWidth: ,idealWidth: ,maxWidth..)

cssでいうwidth,height,

fixedSizeモディファイア

ビューの表示を固定

func fixedSize() -> some View
func fixedSize(horizontal:Bool,vertical:Bool) -> some View
horizontal 横方向のはみ出しを許すか
vertical 縦方向のはみ出しを許すか

borderモディファイア

境界線を表示

func border(content:境界線のスタイル ,width:線の太さ )
contentにはColor,ImagePaint,LinearGradient,RadialGradientなどが入る

cssでいうborder

positionモディファイア

ビューの中心を親の座標空間の指定された座標に配置

func position(x: .y: ) -> some View

positionを指定するとそれまでのframeの設定がリセットされる、フレームサイズは強制的に親ビューと同じになる。フレームサイズを指定してその中に座標系を作りたい時はpositionの後にframeモディファイアを指定。
cssでいうtop,bottom,left,right

offsetモディファイア

元の位置を基準としてビューの表示位置をずらす

func offset(x:横方向へずらす距離, y:縦方向にずらす距離)

cssでいうmargin

edgesIgnoringSafeAreaモディファイア

指定された辺に対して、ビューの配置可能領域をセーフエリアの外へ拡張

func edgeIgnoringSafeArea(_ edges: Edge.Set) -> some View
引数edgesの種類top,bottom,leading,trailing,horizontal,vertical,all

.edgesIgnoringSafeArea(.vertical)

paddingモディファイア

ビューの周りの余白を追加
cssと同じ

func padding(_ length: CGFloat) -> some View
引数にはtop,leading,bottom,trailingを指定できる

.padding(.init(top:10,bottom:30,trailing:50))

backgroundモディファイア

背景設定

.background(Image("aaa_image"))
.background(Color.yellow)

cssと同じ

foregroundColorモディファイア

ビューの前景要素に使う色を設定
テキストビューの場合文字色の指定
cssのcolorと同じ?

.foregroundColor(Color.yellow)

overlayモディファイア

ビューの前に別のビューを重ねて配置
重ねるビューのサイズは元のビューサイズに制限される
画像にキャプションを付けることも可能

Image("logo-image")
    .overlay(
     Text("hello")
     font(.largeTitle)
     .foregroundColor(.white)
     .padding(),
     alignment: .top)

*要素のサイズがフレームに収まりきらないときに切り捨てられるのはテキストビュー特有の動作

clippedモディファイア

ビューをフレームの境界で切り取る
定義func clipped(animated: Bool) -> some View

Image("aaa_image")
    .frame(width:100,height:100)
    .clipped()

clipShapeモディファイア

ビューの切り取り形状を指定
シェイプの種類
Capsule-カプセル状
Circle-円
Ellipse-楕円
Path-任意のパス
Rectangle-四角形
RoundedRectangle-角丸四角形

Image("aaa_image")
    .clipShape(Circle())

maskモディファイア

引数のビューを使ってマスクする

Image("haikei_image")
    .mask(Image("temae_image"))
ビューを透過させることも出来る
.mask(Color(red:0.0,blue:0.0,green:0.0,opacity:0.5))

cornerRadiusモディファイア

指定されたコーナーの半径でビューを角丸にクリップ
cssのborder-radiusと同じ

Image("aaa_image")
    .cornerRadius(10)
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む