Swift

since 2022-12-05

The Swift Programming Language(日本語版)

https://www.swiftlangjp.com/

REPL

% swift repl  
Welcome to Apple Swift version 5.7.1 (swiftlang-5.7.1.135.3 clang-1400.0.29.51).
Type :help for assistance.
  1> var a = "Hello"
a: String = "Hello"
  2> print(a)
Hello
  3> print(a + " Swift")
Hello Swift
  4>  

Swift Package Manager

% mkdir hello
% cd hello
% swift package init --name hello --type executable
Creating library package: hello
Creating Package.swift
Creating README.md
Creating .gitignore
Creating Sources/
Creating Sources/hello/hello.swift
Creating Tests/
Creating Tests/helloTests/
Creating Tests/helloTests/helloTests.swift
% swift run
Building for debugging...
[3/3] Linking hello
Build complete! (0.96s)
Hello, World!
% swift test     
Building for debugging...
[3/3] Linking helloPackageTests
Build complete! (12.87s)
Test Suite 'All tests' started at 2022-12-13 10:01:34.569
Test Suite 'helloPackageTests.xctest' started at 2022-12-13 10:01:34.570
Test Suite 'helloTests' started at 2022-12-13 10:01:34.571
Test Case '-[helloTests.helloTests testExample]' started.
Test Case '-[helloTests.helloTests testExample]' passed (0.004 seconds).
Test Suite 'helloTests' passed at 2022-12-13 10:01:34.574.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.004 (0.004) seconds
Test Suite 'helloPackageTests.xctest' passed at 2022-12-13 10:01:34.574.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.004 (0.004) seconds
Test Suite 'All tests' passed at 2022-12-13 10:01:34.574.
	 Executed 1 test, with 0 failures (0 unexpected) in 0.004 (0.005) seconds
% ./.build/x86_64-apple-macosx/debug/hello
Hello, World!
% file ./.build/x86_64-apple-macosx/debug/hello
./.build/x86_64-apple-macosx/debug/hello: Mach-O 64-bit executable x86_64
% cat Sources/hello/hello.swift
@main
public struct hello {
    public private(set) var text = "Hello, World!"
 
    public static func main() {
        print(hello().text)
    }
}
% cat Tests/helloTests/helloTests.swift 
import XCTest
@testable import hello
 
final class helloTests: XCTestCase {
    func testExample() throws {
        // This is an example of a functional test case.
        // Use XCTAssert and related functions to verify your tests produce the correct
        // results.
        XCTAssertEqual(hello().text, "Hello, World!")
    }
}

Boot Camp Text で Python と比較

唐突に Python と Swift を比較してみようと思った。

https://pycamp.pycon.jp/textbook/ を Swift で書いてみる。Xcode 14.1 の Playground で動作を確認する。

fizzbuzz

第一段階。まず引数をそのまま返す関数を作って100回実行する。

func fizzbuzz(_ num: Int) -> Int {
    return num
}
 
for num in 1...100 {
    print(fizzbuzz(num))
 
}
  • 1..<101 とも書ける
  • 関数定義で _ をつけるのは「外部引数名の省略」のため。つけない場合は、呼び出す側では fizzbuzz(num:num) と書く。

第2段階。

func fizzbuzz(_ num: Int) -> String {
    if num % 3 == 0 && num % 5 == 0 {
        return "FizzBuzz"
    } else if num % 3 == 0 {
        return "Fizz"
    } else if num % 5 == 0 {
        return "Buzz"
    }
    return String(num)
}
 
for num in 1...100 {
    print(fizzbuzz(num))
}
  • 論理演算子は and ではなく &&
  • 文字列リテラルでシングルクオートは使えない
  • Int を文字列に型変換するには String(値)

定数と変数

let a = 1
print(a)
//a = 2
//print(a)
var b = 2
print(b)
b = 3
print(b)
//b = "4"
//print(b)
 
出力
 
1
2
3
  • let は定数。a=2 のコメントアウトを外すとエラー
  • var は変数。初期値の型を代入できる。b="4" のコメントアウトを外すとエラー
var c: Float = 5
print(c)
 
出力
 
5.0
  • 変数の宣言で型を記述できる

べき乗

import Foundation
print(pow(5,2))
  • 5**2 はべき乗ではないので pow 関数を使う
  • pow 関数を使うには Foundation などのインポートが必要

文字列

print("Hello\"world")
var a = 1
print("Hello \(a) world")
Hello"world
Hello 1 world

複数行文字列リテラル

print("""
foo
bar
baz
""")
  • 開始の """ の直後には何も書かない
  • 終了の """ の直前にも何も書かない
print("spam" + "ham")
  • 足し算はできる
  • 掛け算はできない
let s = "swift"
let i = s.startIndex
print(s[i])
 
結果
 
s

コレクション

var a : [Any] = ["spam", "egg", 0.5]
print(a)
  • 中身の型が揃っていない配列を作るには Any 型指定が必要
a += ["ham"] // a = a + ["ham"]
 
a[1]
for animal in ["cat", "dog", "snake"] {
    print(animal)
}
  • これだけみると Python そっくりなのに

コレクションは配列、辞書、集合

タプル

var (dog, cat) = ("dog", "cat")
print(dog, cat)
  • ここだけ見てるとコレクションっぽいというか Python っぽい
var animals = ("dog", "cat")
print(animals)
print(animals.0)
print(animals.1)
//for animal in animals {
//    print(animal)
//}
  • for は使えない。シーケンスではないと言われる。
let http200Status = (statusCode: 200, description: "OK")
print(http200Status.statusCode)
let (statusCode, _) = http200Status
print(statusCode)

ファイル操作

Playground でテキストファイルの読み書き、意外に大変

https://stackoverflow.com/questions/24245916/how-can-i-read-a-file-in-a-swift-playground

日付

import Foundation
var d = NSDate()
print(d)
var d2 = Date()
print(d2)

正規表現

Swift 5.7 の新機能

https://www.hackingwithswift.com/swift/5.7/regexes

そのまま引用

let search1 = /My name is (.+?) and I'm (\d+) years old./
let greeting1 = "My name is Taylor and I'm 26 years old."
if let result = try? search1.wholeMatch(in: greeting1) {
    print("Name: \(result.1)")
    print("Age: \(result.2)")
}

もうしわけないので if let ではなく guard let else return に書き換えてみる

func hello() {
    let search1 = /My name is (.+?) and I'm (\d+) years old./
    let greeting1 = "My name is Taylor and I'm 26 years old."
    guard let result = try? search1.wholeMatch(in: greeting1) else { return }
    print("Name: \(result.1)")
    print("Age: \(result.2)")
}
hello()

https://speakerdeck.com/ainame/swift-5-dot-7debian-waruzheng-gui-biao-xian-woshi-sitemiyou

SwiftUI

文献

末尾クロージャー

SwiftUI APIの設計技術:プログレッシブディスクロージャ

https://developer.apple.com/videos/play/wwdc2022/10059/

<html> <blockquote class="twitter-tweet"><p lang="ja" dir="ltr">先に見てたのはこっちで、なるほどシンタックスシュガーとデフォルト動作がすごい作り込まれてることがわかった<a href="https://twitter.com/hashtag/wwdc22?src=hash&amp;ref_src=twsrc%5Etfw">#wwdc22</a> SwiftUI APIの設計技術:プログレッシブディスクロージャ <a href="https://t.co/lUiqLFz7XH">https://t.co/lUiqLFz7XH</a></p>&mdash; にしもつ (@24motz) <a href="https://twitter.com/24motz/status/1601522343976701952?ref_src=twsrc%5Etfw">December 10, 2022</a></blockquote> <script async src="https://platform.twitter.com/widgets.js" charset="utf-8"></script> </html>

Button(action: { a = 1 }) {
    Text("Label")
}
 
// 以下のように書ける
 
Button("Label") { a = 1 }

しかも第1引数は localized string key で、英語で書いて Localizable.strings (ja) をあとで書けば2ヶ国語対応になる。

ちゃんと書いてあった。

https://developer.apple.com/documentation/swiftui/button

そして action は trailing closure として書けるのか。

https://docs.swift.org/swift-book/LanguageGuide/Closures.html

https://www.swiftlangjp.com/language-guide/closures.html#%E6%9C%AB%E5%B0%BE%E3%82%AF%E3%83%AD%E3%83%BC%E3%82%B8%E3%83%A3trailing-closures

ボタンを押すとアラートを出して、さらに OK を押させる。

Instance Method alert(_:isPresented:actions:)

公式のサンプルを改変。

struct ContentView: View {
    @State private var didSave = false
    var body: some View {
        Button("Save") {
            didSave = true
        }
        .alert(
            "Saved.",
            isPresented: $didSave
        ) {
            Button("OK") {
                print("OK is pressed")
            }
        }
    }
}

print の出力はプレビューではなくシミュレーターで実行すると確認できる。

State didSave はOKを押したときに false に戻る。

あえて冗長に書くと

struct ContentView: View {
    @State private var didSave = false
    var body: some View {
        Button(
            action: {
                didSave = true
            },
            label: {
                Text("Hello")
            }
        )
        .alert(
            "Saved.",
            isPresented: $didSave,
            actions: {
                Button(
                    action: {
                        print("OK is pressed")
                    },
                    label: {
                        Text("OK")
                    }
                )
            }
        )
    }
}

repl で末尾クロージャーを試す

  1> var names = ["cat", "dog", "snake"]
names: [String] = 3 values {
  [0] = "cat"
  [1] = "dog"
  [2] = "snake"
}
  2> names.sorted { $0 > $1 }
$R0: [String] = 3 values {
  [0] = "snake"
  [1] = "dog"
  [2] = "cat"
}
  3> names.sorted { $0.count < $1.count }
$R1: [String] = 3 values {
  [0] = "cat"
  [1] = "dog"
  [2] = "snake"
}

Ruby だと

names = ["cat", "dog", "snake"]
names.sort { |a,b| a.length <=> b.length }  # => ["cat", "dog", "snake"]
names.sort { _1.length <=> _2.length }  # => ["cat", "dog", "snake"]
swift.txt · 最終更新: 2022/12/15 22:34 by Takuya Nishimoto
www.chimeric.de Valid CSS Driven by DokuWiki do yourself a favour and use a real browser - get firefox!! Recent changes RSS feed Valid XHTML 1.0