Share
Embed
Transcript
53 slides
-
"CPVUNF struct Me { let name = "Takuhiro Muta" let
aka = "417.72KI" let company = "(redacted)" let twitter = "417_72ki" let qiita = "417_72ki" let gitHub = "417-72KI" let products = [ "MockUserDefaults", "MultipartFormDataParser", "BuildConfig.swift", "SSGH" ] let contributing = [ "Danger-Swift", "octokit.swift", "etc..." ] } -
'JOEBOE3FQMBDFJO1BDLBHF w Ұݟྑͦ͞͏ʹݟ͑Δ͕ w ͤʔͷͰҰ੪ʹॻ͖ΘΔ w ཏੑେৎʁ w ֘GVODUJPOҎ֎ʹಉ͡UZQP͕͋ͬͨ࣌ͦͬͪมΘΔ w
ςετ͖͠ΕΔʁ w UZQPΛमਖ਼ͨ݁͠ՌผͷGVODUJPOͱඃͬͨ w ҙਤͤ͵όάͷੜ 🤔 -
'JOEBOE3FQMBDFJO1BDLBHF // A.swift func doSomesing() { // do something }
// C.swift func doSomething(with foo: Foo = .init()) { // do something with `foo` } // B.swift func call() { doSomesing() } // D.swift func callWithFoo() { doSomething() } -
'JOEBOE3FQMBDFJO1BDLBHF // A.swift func doSomething() { // do something }
// C.swift func doSomething(with foo: Foo = .init()) { // do something with `foo` } // B.swift func call() { doSomething() } // D.swift func callWithFoo() { doSomething() } 😱 -
BWBJMBCMFʹ͍ͭͯ ओͳΦϓγϣϯ w ܯࠂ w EFQSFDBUFEඇਪ όʔδϣϯলུՄ w ϏϧυΤϥʔ
w PCTPMFUFEഇࢭ όʔδϣϯলུෆՄ w VOBWBJMBCMFར༻ෆՄ όʔδϣϯࢦఆෆՄ -
@available(*, deprecated, renamed: "doSomething()") func doSomesing() { doSomething() } func
doSomething() { // do something } -
αϙʔτόʔδϣϯͷؔͰ͑ͳ͍"1* ˞J04 ͷ"QQΛఆ w JGBWBJMBCMFΛͬͯ w 8PSLBSPVOEͱซ༻͢Δ w ্ҐόʔδϣϯͷΈ͑ΔΑ͏ʹ͢Δ w
FY w "UUSJCVUFE4USJOH J04d w QSFTFOUBUJPO%FUFOUT J04d -
αϙʔτόʔδϣϯͷؔͰ͑ͳ͍"1* ˞J04 ͷ"QQΛఆ w JGBWBJMBCMFΛͬͯ w 8PSLBSPVOEͱซ༻͢Δ w ্ҐόʔδϣϯͷΈ͑ΔΑ͏ʹ͢Δ w
FY w "UUSJCVUFE4USJOH J04d w QSFTFOUBUJPO%FUFOUT J04d -
"UUSJCVUFE4USJOH var attributedString: AttributedString { // ← 'AttributedString' is only
available in iOS 15 or newer var str = AttributedString("Foo Bar Baz Qux Quux") if let range = str.range(of: "Bar") { str[range].foregroundColor = .red } if let range = str.range(of: "Baz") { str[range].font = .title } if let range = str.range(of: "Qux") { str[range].font = .footnote str[range].foregroundColor = .green } return str } var body: some View { VStack { Text(attributedString) // ← 'init(_:)' is only available in iOS 15.0 or newer } } -
"UUSJCVUFE4USJOH @available(iOS 15, *) var attributedString: AttributedString { var str
= AttributedString("Foo Bar Baz Qux Quux") if let range = str.range(of: "Bar") { str[range].foregroundColor = .red } if let range = str.range(of: "Baz") { str[range].font = .title } if let range = str.range(of: "Qux") { str[range].font = .footnote str[range].foregroundColor = .green } return str } var body: some View { VStack { Text(attributedString) // ← 'init(_:)' is only available in iOS 15.0 or newer } } -
"UUSJCVUFE4USJOH var body: some View { VStack { if #available(iOS
15, *) { Text(attributedString) } else { Text("Foo") + Text(" ") + Text("Bar") .foregroundColor(.red) + Text(" ") + Text("Baz") .font(.title) + Text(" ") + Text("Qux") .font(.footnote) .foregroundColor(.green) + Text(" ") + Text("Quux") } } } @available(iOS 15, *) var attributedString: AttributedString { var str = AttributedString("Foo Bar Baz Qux Quux") if let range = str.range(of: "Bar") { str[range].foregroundColor = .red } if let range = str.range(of: "Baz") { str[range].font = .title } if let range = str.range(of: "Qux") { str[range].font = .footnote str[range].foregroundColor = .green } return str } -
"UUSJCVUFE4USJOH var body: some View { VStack { if #available(iOS
15, *) { Text(attributedString) } else { AttributedText { Text("Foo") Text(" ") Text("Bar") .foregroundColor(.red) Text(" ") Text("Baz") .font(.title) Text(" ") Text("Qux") .font(.footnote) .foregroundColor(.green) Text(" ") Text("Quux") } } } } struct AttributedText: View { typealias Body = Text var text: Text init(@Builder builder: () -> Text) { text = builder() } var body: Text { text } } extension AttributedText { @resultBuilder enum Builder { ɾɾɾ } } -
"UUSJCVUFE4USJOH ଋ͞Εٕͨज़తෛ࠴Λ·Ͱ͓֮͑ͯͨ͘Ίʹ var body: some View { VStack { AttributedText
{ Text("Foo") Text(" ") Text("Bar") .foregroundColor(.red) Text(" ") Text("Baz") .font(.title) Text(" ") Text("Qux") .font(.footnote) .foregroundColor(.green) Text(" ") Text("Quux") } } } struct AttributedText: View { typealias Body = Text var text: Text init(@Builder builder: () -> Text) { text = builder() } var body: Text { text } } extension AttributedText { @resultBuilder enum Builder { ɾɾɾ } } -
"UUSJCVUFE4USJOH .JOJNVN%FQMPZNFOU5BSHFU͕ҎԼͷؒܯࠂ͕ग़ͳ͍ @available(iOS, deprecated: 15.0, obsoleted: 16.0, message: "Use `Text`
with `AttributedString`") struct AttributedText: View { typealias Body = Text var text: Text init(@Builder builder: () -> Text) { text = builder() } var body: Text { text } } @available(iOS, deprecated: 15.0, obsoleted: 16.0, message: "Use `Text` with `AttributedString`") extension AttributedText { @resultBuilder enum Builder { ɾɾɾ } } var body: some View { VStack { AttributedText { Text("Foo") Text(" ") Text("Bar") .foregroundColor(.red) Text(" ") Text("Baz") .font(.title) Text(" ") Text("Qux") .font(.footnote) .foregroundColor(.green) Text(" ") Text("Quux") } } } -
"UUSJCVUFE4USJOH .JOJNVN%FQMPZNFOU5BSHFUΛʹͨ͠Βܯࠂ͕ग़Δ @available(iOS, deprecated: 15.0, obsoleted: 16.0, message: "Use `Text`
with `AttributedString`") struct AttributedText: View { typealias Body = Text var text: Text init(@Builder builder: () -> Text) { text = builder() } var body: Text { text } } @available(iOS, deprecated: 15.0, obsoleted: 16.0, message: "Use `Text` with `AttributedString`") extension AttributedText { @resultBuilder enum Builder { ɾɾɾ } } var body: some View { VStack { AttributedText { // ← 'AttributedText' was deprecated in iOS 15.0: Use `Text` with `AttributedString` Text("Foo") Text(" ") Text("Bar") .foregroundColor(.red) Text(" ") Text("Baz") .font(.title) Text(" ") Text("Qux") .font(.footnote) .foregroundColor(.green) Text(" ") Text("Quux") } } } -
"UUSJCVUFE4USJOH .JOJNVN%FQMPZNFOU5BSHFUΛʹͨ͠ΒϏϧυΤϥʔʹ @available(iOS, deprecated: 15.0, obsoleted: 16.0, message: "Use `Text`
with `AttributedString`") struct AttributedText: View { typealias Body = Text var text: Text init(@Builder builder: () -> Text) { text = builder() } var body: Text { text } } @available(iOS, deprecated: 15.0, obsoleted: 16.0, message: "Use `Text` with `AttributedString`") extension AttributedText { @resultBuilder enum Builder { ɾɾɾ } } var body: some View { VStack { AttributedText { // ← 'AttributedText' is unavailable in iOS: Use `Text` with `AttributedString` Text("Foo") Text(" ") Text("Bar") .foregroundColor(.red) Text(" ") Text("Baz") .font(.title) Text(" ") Text("Qux") .font(.footnote) .foregroundColor(.green) Text(" ") Text("Quux") } } } -
"UUSJCVUFE4USJOH JGBWBJMBCMF \^FMTF\^ͰׅΒΕΔͱܯࠂ͕ग़ͳ͍ var body: some View { VStack {
if #available(iOS 15, *) { Text(attributedString) } else { AttributedText { Text("Foo") Text(" ") Text("Bar") .foregroundColor(.red) Text(" ") Text("Baz") .font(.title) Text(" ") Text("Qux") .font(.footnote) .foregroundColor(.green) Text(" ") Text("Quux") } } } } @available(iOS, deprecated: 15.0, obsoleted: 16.0, message: "Use `Text` with `AttributedString`") struct AttributedText: View { typealias Body = Text var text: Text init(@Builder builder: () -> Text) { text = builder() } var body: Text { text } } @available(iOS, deprecated: 15.0, obsoleted: 16.0, message: "Use `Text` with `AttributedString`") extension AttributedText { @resultBuilder enum Builder { ɾɾɾ } } -
var body: some View { VStack { if #available(iOS 15,
*) { Text(attributedString) } else { AttributedText { // ← 'AttributedText' is unavailable in iOS: Use `Text` with `AttributedString` Text("Foo") Text(" ") Text("Bar") .foregroundColor(.red) Text(" ") Text("Baz") .font(.title) Text(" ") Text("Qux") .font(.footnote) .foregroundColor(.green) Text(" ") Text("Quux") } } } } "UUSJCVUFE4USJOH PCTPMFUFEʹ͢ΔͱΤϥʔʹͳΔ @available(iOS, obsoleted: 15.0, message: "Use `Text` with `AttributedString`") struct AttributedText: View { typealias Body = Text var text: Text init(@Builder builder: () -> Text) { text = builder() } var body: Text { text } } @available(iOS, obsoleted: 15.0, message: "Use `Text` with `AttributedString`") extension AttributedText { @resultBuilder enum Builder { ɾɾɾ } } -
αϙʔτόʔδϣϯͷؔͰ͑ͳ͍"1* ˞J04 ͷ"QQΛఆ w JGBWBJMBCMFΛͬͯ w 8PSLBSPVOEͱซ༻͢Δ w ্ҐόʔδϣϯͷΈ͑ΔΑ͏ʹ͢Δ w
FY w "UUSJCVUFE4USJOH J04d w QSFTFOUBUJPO%FUFOUT J04d -
QSFTFOUBUJPO%FUFOUT struct ContentView: View { @State private var isPresenting =
false var body: some View { VStack { Button { isPresenting = true } label: { VStack { Image(systemName: "globe") .imageScale(.large) Text("Hello, world!") }.foregroundColor(.accentColor) .padding() } .sheet(isPresented: $isPresenting) { SheetView() .presentationDetents([.medium]) // ← 'presentationDetents' is only available in iOS 16.0 or newer } } } } -
QSFTFOUBUJPO%FUFOUT struct ContentView: View { @State private var isPresenting =
false var body: some View { VStack { Button { isPresenting = true } label: { VStack { Image(systemName: "globe") .imageScale(.large) Text("Hello, world!") }.foregroundColor(.accentColor) .padding() } .sheet(isPresented: $isPresenting) { if #available(iOS 16.0, *) { SheetView() .presentationDetents([.medium]) } else { SheetView() } } } } } -
QSFTFOUBUJPO%FUFOUT GVODUJPOʹΓग़͢ extension View { @ViewBuilder func halfSheetIfAble(height: CGFloat? =
nil) -> some View { if #available(iOS 16.0, *) { if let height { presentationDetents([.height(height)]) } else { presentationDetents([.medium]) } } else { self } } } struct ContentView: View { @State private var isPresenting = false var body: some View { VStack { Button { isPresenting = true } label: { VStack { Image(systemName: "globe") .imageScale(.large) Text("Hello, world!") }.foregroundColor(.accentColor) .padding() } .sheet(isPresented: $isPresenting) { SheetView() .halfSheetIfAble() } } } } -
QSFTFOUBUJPO%FUFOUT struct ContentView: View { @State private var isPresenting =
false var body: some View { VStack { Button { isPresenting = true } label: { VStack { Image(systemName: "globe") .imageScale(.large) Text("Hello, world!") }.foregroundColor(.accentColor) .padding() } .sheet(isPresented: $isPresenting) { SheetView() .halfSheetIfAble() } } } } @available(iOS, deprecated: 16, message: "Use `presentationDetents` directly.") extension View { @ViewBuilder func halfSheetIfAble(height: CGFloat? = nil) -> some View { if #available(iOS 16.0, *) { if let height { presentationDetents([.height(height)]) } else { presentationDetents([.medium]) } } else { self } } } -
QSFTFOUBUJPO%FUFOUT .JOJNVN%FQMPZNFOU5BSHFUΛʹ͢Δͱܯࠂ͕ग़Δ struct ContentView: View { @State private var isPresenting
= false var body: some View { VStack { Button { isPresenting = true } label: { VStack { Image(systemName: "globe") .imageScale(.large) Text("Hello, world!") }.foregroundColor(.accentColor) .padding() } .sheet(isPresented: $isPresenting) { SheetView() .halfSheetIfAble() // ← 'halfSheetIfAble(height:)' was deprecated in iOS 16: Use `presentationDetents` directly. } } } } @available(iOS, deprecated: 16, message: "Use `presentationDetents` directly.") extension View { @ViewBuilder func halfSheetIfAble(height: CGFloat? = nil) -> some View { if #available(iOS 16.0, *) { if let height { presentationDetents([.height(height)]) } else { presentationDetents([.medium]) } } else { self } } } -
QSFTFOUBUJPO%FUFOUT ผղಉ໊ͷCBDLQPSUGVODUJPOΛ༻ҙ͢Δ struct ContentView: View { @State private var isPresenting
= false var body: some View { VStack { Button { isPresenting = true } label: { VStack { Image(systemName: "globe") .imageScale(.large) Text("Hello, world!") }.foregroundColor(.accentColor) .padding() } .sheet(isPresented: $isPresenting) { SheetView() .presentationDetents([.medium]) } } } } @available(iOS, obsoleted: 16, message: "Use `presentationDetents` in SwiftUI directly.") extension View { @ViewBuilder func presentationDetents(_ detents: Set<PresentationDetent>) -> some View { if #available(iOS 16.0, *) { presentationDetents(Set(detents.map(\.detent))) } else { self } } } /// Backporting for `SwiftUI.PresentationDetent` enum PresentationDetent: Hashable { ɾɾɾ } @available(iOS 16.0, *) extension PresentationDetent { var detent: SwiftUI.PresentationDetent { switch self { case .medium: return .medium ɾɾɾ } } } -
QSFTFOUBUJPO%FUFOUT .JOJNVN%FQMPZNFOU5BSHFUΛʹ͢ΔͱϏϧυΤϥʔ struct ContentView: View { @State private var isPresenting
= false var body: some View { VStack { Button { isPresenting = true } label: { VStack { Image(systemName: "globe") .imageScale(.large) Text("Hello, world!") }.foregroundColor(.accentColor) .padding() } .sheet(isPresented: $isPresenting) { SheetView() .presentationDetents([.medium]) / / ← Ambiguous use of 'medium' } } } } @available(iOS, deprecated: 16, message: "Use `presentationDetents` in SwiftUI directly.") extension View { @ViewBuilder func presentationDetents(_ detents: Set<PresentationDetent>) -> some View { if #available(iOS 16.0, *) { presentationDetents(Set(detents.map(\.detent))) } else { self } } } /// Backporting for `SwiftUI.PresentationDetent` enum PresentationDetent: Hashable { ɾɾɾ } @available(iOS 16.0, *) extension PresentationDetent { var detent: SwiftUI.PresentationDetent { switch self { case .medium: return .medium ɾɾɾ } } } -
QSFTFOUBUJPO%FUFOUT CBDLQPSUGVODUJPOΛফͤܯࠂফ͑Δ struct ContentView: View { @State private var isPresenting
= false var body: some View { VStack { Button { isPresenting = true } label: { VStack { Image(systemName: "globe") .imageScale(.large) Text("Hello, world!") }.foregroundColor(.accentColor) .padding() } .sheet(isPresented: $isPresenting) { SheetView() .presentationDetents([.medium]) } } } } //@available(iOS, obsoleted: 16, message: "Use `presentationDetents` in SwiftUI directly.") //extension View { // @ViewBuilder // func presentationDetents(_ detents: Set<PresentationDetent>) -> some View { // if #available(iOS 16.0, *) { // presentationDetents(Set(detents.map(\.detent))) // } else { // self // } // } //} // ///// Backporting for `SwiftUI.PresentationDetent` //enum PresentationDetent: Hashable { // ɾɾɾ //} // //@available(iOS 16.0, *) //extension PresentationDetent { // var detent: SwiftUI.PresentationDetent { // switch self { // case .medium: return .medium // ɾɾɾ // } // } //}