
IOS рдХреЗ рд╡рд┐рдХрд╛рд╕ рдореЗрдВ рдПрдХ рд╕рд╛рдорд╛рдиреНрдп рдХрд╛рд░реНрдп UITableView рдореЗрдВ рд╡рд┐рд╕реНрддрд╛рд░ рдпреЛрдЧреНрдп / рддрд╣ рдЕрдиреБрднрд╛рдЧ рд╣реИред рдЖрдЬ рд╣рдо SwiftUI рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕ рдХрд╛рд░реНрдп рдХреЛ рд╕рд╛рдХрд╛рд░ рдХрд░ рд░рд╣реЗ рд╣реИрдВред рдПрдХ рдЫреЛрдЯреЗ рд╕реЗ рдореЛрдбрд╝ рдХреЗ рд░реВрдк рдореЗрдВ, рдЕрдиреБрднрд╛рдЧ рд╣реЗрдбрд░ рдореЗрдВ рдПрдХ рдПрдирд┐рдореЗрдЯреЗрдб рддреНрд░рд┐рдХреЛрдг рдЬреЛрдбрд╝реЗрдВ рдФрд░ рдХреЛрд╢рд┐рдХрд╛рдУрдВ рдХреЛ рднреА рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдХрд░реЗрдВред
MacOS Catalina 10.15.1 рдХреЗ рд▓рд┐рдП Xcode 11.2 рдкрд░ рд╡рд┐рдХрд╛рд╕ рд╣реБрдЖ
рдкреНрд░реЛрдЬреЗрдХреНрдЯ рд╢реБрд░реВ рдХрд░реЗрдВ
рд▓реЙрдиреНрдЪ Xcode, рдлрд╝рд╛рдЗрд▓ - рдирдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ - рдПрдХрд▓ рджреГрд╢реНрдп рдРрдкред рд╕рдВрд╡рд╛рдж рдмреЙрдХреНрд╕ рдореЗрдВ, рд╕реНрд╡рд┐рдлреНрдЯ рд╡рд┐рдХрд╛рд╕ рднрд╛рд╖рд╛ рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВ, рд╣рдо SwiftUI рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдпреВрдЖрдИ рдмрдирд╛рдПрдВрдЧреЗред

рдбреЗрдЯрд╛
рдкреНрд░рджрд░реНрд╢рди рдбреЗрдЯрд╛ рдХреЗ рд░реВрдк рдореЗрдВ, рд╣рдо рд▓реИрдЯрд┐рди рдореЗрдВ рд░реВрд╕реА рдореЗрдВ рдЙрдирдХреЗ рдЕрдиреБрд╡рд╛рдж рдХреЗ рд╕рд╛рде рдХрдИ рдордЬрд╝реЗрджрд╛рд░ рдкрдВрдЦреЛрдВ рд╡рд╛рд▓реЗ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐рдпреЛрдВ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░реЗрдВрдЧреЗред
рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдПрдХ рдирдИ рд╕реНрд╡рд┐рдлреНрдЯ рдлрд╝рд╛рдЗрд▓ рдЬреЛрдбрд╝реЗрдВ, рдЗрд╕реЗ
Data.swift рдХрд╣реЗрдВ рдФрд░ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рд▓рд┐рдЦ рджреЗрдВ:
struct QuoteDataModel : Identifiable { var id: String { return latin } var latin : String var russian : String var expanded = false } struct SectionDataModel : Identifiable { var id: Character { return letter } var letter : Character var quotes : [QuoteDataModel] var expanded = false }
QuoteDataModel рдПрдХ рдПрдХрд▓ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХрд╛ рдПрдХ рдореЙрдбрд▓ рд╣реИ, рднрд╡рд┐рд╖реНрдп рдореЗрдВ рдпрд╣ рдкреНрд░рддреНрдпреЗрдХ рд╡реНрдпрдХреНрддрд┐рдЧрдд рд╕реЗрд▓ рдХреА рд╕рд╛рдордЧреНрд░реА рдмрди рдЬрд╛рдПрдЧрд╛ред рдЗрд╕рдореЗрдВ рд╣рдо рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рдореВрд▓ рдкрд╛рда, рдЙрд╕рдХреЗ рдЕрдиреБрд╡рд╛рдж рдФрд░ "рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд" рд╕реЗрд▓ рдХреЗ рд╕рдВрдХреЗрдд рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреЗ рд╣реИрдВ (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ рдпрд╣ "рдиреНрдпреВрдирддрдо" рд╣реИ)
SectionDataModel рдкреНрд░рддреНрдпреЗрдХ рдЕрд▓рдЧ рд╕реЗрдХреНрд╢рди рдХрд╛ рдПрдХ рдореЙрдбрд▓ рд╣реИ, рдпрд╣рд╛рдБ рд╣рдо рдЕрдиреБрднрд╛рдЧ рдХреЗ "рдЕрдХреНрд╖рд░" рдХреЛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддреЗ рд╣реИрдВ, рдЗрд╕ рдкрддреНрд░ рдХреЗ рд╕рд╛рде рд╢реБрд░реВ рд╣реЛрдиреЗ рд╡рд╛рд▓реЗ рдЙрджреНрдзрд░рдгреЛрдВ рдХреА рдПрдХ рд╕рд░рдгреА рдФрд░ "рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд" рдЦрдВрдб рдХрд╛ рдПрдХ рд╕рдВрдХреЗрдд (рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ "рдврд╣ рдЧрдпрд╛")
рднрд╡рд┐рд╖реНрдп рдореЗрдВ, рд╣рдо рдПрдХ рд╕реВрдЪреА рджреГрд╢реНрдп рдореЗрдВ рдпрд╣ рд╕рдм рдкреНрд░рджрд░реНрд╢рд┐рдд рдХрд░реЗрдВрдЧреЗ, рдЬрд┐рд╕рдХреЗ рд▓рд┐рдП рдЖрд╡рд╢реНрдпрдХ рд╣реИ рдХрд┐ рдЗрд╕рдХреЗ рд▓рд┐рдП рдбреЗрдЯрд╛
рдкрд╣рдЪрд╛рди рдпреЛрдЧреНрдп рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рдЕрдиреБрдкрд╛рд▓рди рдХрд░реЗред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдо
рдЖрдИрдбреА рдкреНрд░реЙрдкрд░реНрдЯреА рдХреЛ рдкрд░рд┐рднрд╛рд╖рд┐рдд рдХрд░рддреЗ рд╣реИрдВ, рдЬреЛ рд╕реВрдЪреА рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЖрдЗрдЯрдо рдХреЗ рд▓рд┐рдП рдЕрджреНрд╡рд┐рддреАрдп рд╣реЛрдиреА рдЪрд╛рд╣рд┐рдПред
рдЗрд╕рдХреЗ рдЕрд▓рд╛рд╡рд╛, рдЙрд╕реА Data.swift рдлрд╝рд╛рдЗрд▓ рдореЗрдВ, рд╣рдо рдЕрдкрдирд╛ рдбреЗрдЯрд╛ рдмрдирд╛рддреЗ рд╣реИрдВ:
var latinities : [SectionDataModel] = [ SectionDataModel(letter: "C", quotes: [ QuoteDataModel(latin: "Calvitium non est vitium, sed prudentiae indicium.", russian: " , ."), QuoteDataModel(latin: "Conjecturalem artem esse medicinam.", russian: " ."), QuoteDataModel(latin: "Crede firmiter et pecca fortiter!", russian: " !")]), SectionDataModel(letter: "H", quotes: [ QuoteDataModel(latin: "Homo sine religione sicut equus sine freno.", russian: " ."), QuoteDataModel(latin: "Habet et musca splenem.", russian: " .")]), SectionDataModel(letter: "M", quotes: [ QuoteDataModel(latin: "Malum est mulier, sed necessarium malum.", russian: " , ."), QuoteDataModel(latin: "Mulierem ornat silentium.", russian: " .")])]
рдЖрдЗрдП рдЗрдВрдЯрд░рдлрд╝реЗрд╕ рд╕реЗ рдирд┐рдкрдЯреЗрдВ
рдЕрдм рд╣рдо рдпрд╣ рдирд┐рд░реНрдзрд╛рд░рд┐рдд рдХрд░реЗрдВрдЧреЗ рдХрд┐ рдЕрдиреБрднрд╛рдЧ рд╢реАрд░реНрд╖ рдФрд░ рдкреНрд░рддреНрдпреЗрдХ рд╕реЗрд▓ рдХреИрд╕рд╛ рджрд┐рдЦреЗрдЧрд╛ред
рдореЗрдиреВ рд╕реЗ рдлрд╝рд╛рдЗрд▓ - рдирдпрд╛ - рдлрд╝рд╛рдЗрд▓ - рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рдЪреБрдиреЗрдВред рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо
HeaderView.swift рд░рдЦреЗрдВ рдФрд░ рдЙрд╕рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдирд┐рдореНрди рдХреЗ рд╕рд╛рде рдмрджрд▓реЗрдВ:
import SwiftUI struct HeaderView : View { var section : SectionDataModel var body: some View { HStack() { Spacer() Text(String(section.letter)) .font(.largeTitle) .foregroundColor(Color.black) Spacer() } .background(Color.yellow) } } struct HeaderView_Previews: PreviewProvider { static var previews: some View { HeaderView(section: latinities[0]) } }

рдЕрдм рдлрд┐рд░ рд╕реЗ рдлрд╛рдЗрд▓ - рдирдпрд╛ - рдлрд╛рдЗрд▓ - рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рд╡реНрдпреВред рдлрд╝рд╛рдЗрд▓ рдХрд╛ рдирд╛рдо
QuoteView.swift рд░рдЦреЗрдВ рдФрд░ рдЙрд╕рдХреА рд╕рд╛рдордЧреНрд░реА рдХреЛ рдирд┐рдореНрдирд▓рд┐рдЦрд┐рдд рдХреЗ рд╕рд╛рде рдмрджрд▓реЗрдВ:
import SwiftUI struct QuoteView: View { var quote : QuoteDataModel var body: some View { VStack(alignment: .leading, spacing: 5) { Text(quote.latin) .font(.title) if quote.expanded { Group() { Divider() Text(quote.russian).font(.body) }.transition(.move(edge: .top)).animation(.default) } } } } struct QuoteView_Previews: PreviewProvider { static var previews: some View { QuoteView(quote: latinities[0].quotes[0]) } }

рдЕрдм ContentView.swift рдлрд╝рд╛рдЗрд▓ рдЦреЛрд▓реЗрдВ рдФрд░ рдирд┐рдореНрдирд╛рдиреБрд╕рд╛рд░ ContentView рдХреА рд╕рдВрд░рдЪрдирд╛ рдмрджрд▓реЗрдВ:
struct ContentView: View { var body: some View { List { ForEach(latinities) { section in Section(header: HeaderView(section: section), footer: EmptyView()) { if section.expanded { ForEach(section.quotes) { quote in QuoteView(quote: quote) } } } } } .listStyle(GroupedListStyle()) } }
рдмрдзрд╛рдИ рд╣реЛ, рдЖрдкрдиреЗ рд╕реВрдЪреА рдХреЛ рдЕрдк-рдЯреВ-рдбреЗрдЯ рдбреЗрдЯрд╛ рдХреЗ рд╕рд╛рде рдЖрдмрд╛рдж рдХрд┐рдпрд╛ рд╣реИ!
рд▓реИрдЯрд┐рдирд┐рдЯреА рдПрд░реЗ рдХреЗ рдкреНрд░рддреНрдпреЗрдХ рддрддреНрд╡ рдХреЗ рд▓рд┐рдП
, рд╣рдо рд╣реЗрдбрд░
рд╡реНрдпреВ рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рд╣реЗрдбрд░ рдХреЗ рд╕рд╛рде рдПрдХ рдЕрдиреБрднрд╛рдЧ
рдмрдирд╛рддреЗ рд╣реИрдВ рдФрд░ рдПрдХ рдЦрд╛рд▓реА рдкрд╛рдж рд▓реЗрдЦ рдХреЗ рд╕рд╛рдеред рдпрджрд┐ рдЕрдиреБрднрд╛рдЧ "рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд" рд╣реИ, рддреЛ рдЙрджреНрдзрд░рдг рд╕рд░рдгреА рдореЗрдВ рдкреНрд░рддреНрдпреЗрдХ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рд▓рд┐рдП рд╣рдо рдЙрджреНрдзрд░рдг рдХреЗ рдЖрдзрд╛рд░ рдкрд░ рдПрдХ рд╕реЗрд▓
рдмрдирд╛рддреЗ рд╣реИрдВ ред рд╣рдорд╛рд░реЗ рдбреЗрдЯрд╛ рдореЗрдВ, рд╕рднреА рдЕрдиреБрднрд╛рдЧ рдФрд░ рд╕рднреА рд╕реЗрд▓ "рдврд╣ рдЧрдП" рд╣реИрдВ, рдЗрд╕рд▓рд┐рдП рдпрджрд┐ рдЖрдк рдХреИрдирд╡рд╛рд╕ рдХреЛ рджреГрд╢реНрдпрдорд╛рди рдмрдирд╛рддреЗ рд╣реИрдВ, рддреЛ рдЖрдк рдХреЗрд╡рд▓ рдЕрдиреБрднрд╛рдЧ рд╣реЗрдбрд░ рджреЗрдЦреЗрдВрдЧреЗ:

рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рд╕рдордЭрддреЗ рд╣реИрдВ, рдЕрдм рдЖрд╡реЗрджрди рдкреВрд░реА рддрд░рд╣ рд╕реЗ "рдореГрдд" рд╣реИ рдФрд░ рдЕрднреА рднреА рд╣рдорд╛рд░реЗ рдЕрдВрддрд┐рдо рд▓рдХреНрд╖реНрдп рд╕реЗ рдмрд╣реБрдд рджреВрд░ рд╣реИред рд▓реЗрдХрд┐рди рдЬрд▓реНрдж рд╣реА рд╣рдо рдЗрд╕реЗ рдареАрдХ рдХрд░ рджреЗрдВрдЧреЗ!
рд╕реЗрдХреНрд╢рди рд╣реЗрдбрд░ рдХреЛ рдереЛрдбрд╝рд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░реЗрдВ
HeaderView.swift рдлрд╝рд╛рдЗрд▓ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВред рд╢реАрд░реНрд╖рд▓реЗрдЦ рджреГрд╢реНрдп рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдЕрдВрджрд░, рд╢рд░реАрд░ рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж, рдЗрд╕реЗ рдЬреЛрдбрд╝реЗрдВ:
struct Triangle : Shape { func path(in rect: CGRect) -> Path { var path = Path() path.move(to: CGPoint(x: 0, y: 0)) path.addLine(to: CGPoint(x: 0, y: rect.height - 1)) path.addLine(to: CGPoint(x: sqrt(3)*(rect.height)/2, y: rect.height/2)) path.closeSubpath() return path } }
рдпрд╣ рд╕рдВрд░рдЪрдирд╛ рдПрдХ рд╕рдордмрд╛рд╣реБ рддреНрд░рд┐рднреБрдЬ рд▓реМрдЯрд╛рддреА рд╣реИред рдЕрдм рд╣рдорд╛рд░реЗ рддреНрд░рд┐рдХреЛрдг рдХреЛ рд╣реЗрдбрд░ рдореЗрдВ рдЬреЛрдбрд╝реЗрдВред рдкрд╣рд▓реЗ
рд╕реНрдкреЗрд╕рд░ рдХреЛ рдЬреЛрдбрд╝рдиреЗ рд╕реЗ рдкрд╣рд▓реЗ,
HStack рдХреЗ рдЕрдВрджрд░:
Triangle() .fill(Color.black) .overlay( Triangle() .stroke(Color.red, lineWidth: 5) ) .frame(width : 50, height : 50) .padding() .rotationEffect(.degrees(section.expanded ? 90 : 0), anchor: .init(x: 0.5, y: 0.5)).animation(.default))

рдбреЗрдЯрд╛ рд╕рдВрд╢реЛрдзрд┐рдд рдХрд░реЗрдВ
рд╣рдорд╛рд░реЗ рдбреЗрдЯрд╛ рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВред Data.swift рдЦреЛрд▓реЗрдВ рдФрд░ рдЗрд╕ рддрд░рд╣ рд╕реЗ рдПрдХ рдирдП UserData рд╡рд░реНрдЧ рдореЗрдВ рд╣рдорд╛рд░реЗ
рд▓реИрдЯрд┐рдирд┐рдЯреА рдРрд░реЗ рдХреЛ
рд▓рдкреЗрдЯреЗрдВ :
class UserData : ObservableObject { @Published var latinities : [SectionDataModel] = [ SectionDataModel(letter: "C", quotes: [ QuoteDataModel(latin: "Calvitium non est vitium, sed prudentiae indicium.", russian: " , ."), QuoteDataModel(latin: "Conjecturalem artem esse medicinam.", russian: " ."), QuoteDataModel(latin: "Crede firmiter et pecca fortiter!", russian: " !")]), SectionDataModel(letter: "H", quotes: [ QuoteDataModel(latin: "Homo sine religione sicut equus sine freno.", russian: " ."), QuoteDataModel(latin: "Habet et musca splenem.", russian: " .")]), SectionDataModel(letter: "M", quotes: [ QuoteDataModel(latin: "Malum est mulier, sed necessarium malum.", russian: " , ."), QuoteDataModel(latin: "Mulierem ornat silentium.", russian: " .")])] }
@Published рдХреЗ рд░реВрдк рдореЗрдВ
рд▓реИрдЯрд┐рди рдХреЛ рднреА рдЪрд┐рд╣реНрдирд┐рдд рдХрд░рдирд╛ рдпрд╛рдж рд░рдЦреЗрдВред
рд╣рдордиреЗ рдХреНрдпрд╛ рдХрд┐рдпрд╛ рд╣реИ?рдСрдмреНрдЬрд░реНрд╡реЗрдмрд▓рдСрдмреНрдЬреЗрдХреНрдЯ рд╣рдорд╛рд░реЗ рдбреЗрдЯрд╛ рдХреЗ рд▓рд┐рдП рдПрдХ рд╡рд┐рд╢реЗрд╖ рд╡рд╕реНрддреБ рд╣реИ рдЬреЛ рдХреБрдЫ рджреГрд╢реНрдп рдХреЗ рд▓рд┐рдП "рдмрд╛рдзреНрдп" рд╣реЛ рд╕рдХрддрд╛ рд╣реИред рд╕реНрд╡рд┐рдлреНрдЯрдпреВрдЖрдИ рд╕рднреА рдкрд░рд┐рд╡рд░реНрддрдиреЛрдВ рдХреЛ "рдореЙрдирд┐рдЯрд░" рдХрд░рддрд╛ рд╣реИ рдЬреЛ рд╡реНрдпреВ рдХреЛ рдкреНрд░рднрд╛рд╡рд┐рдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ рдФрд░, рдбреЗрдЯрд╛ рдмрджрд▓рдиреЗ рдХреЗ рдмрд╛рдж, рд╡реНрдпреВ рдХреЛ рдмрджрд▓рддрд╛ рд╣реИред
рд▓реИрдЯрд┐рди рдХреЗ "рд░реИрдкрд┐рдВрдЧ" рдХреЗ рдмрд╛рдж, рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдмрд╣реБрдд рд╕рд╛рд░реА рддреНрд░реБрдЯрд┐рдпрд╛рдВ рдереАрдВ, рд╣рдо рдЙрдиреНрд╣реЗрдВ рдареАрдХ рдХрд░ рджреЗрдВрдЧреЗред
HeaderView.swift рдЦреЛрд▓реЗрдВ рдФрд░ рдЗрд╕ рдкреНрд░рдХрд╛рд░
HeaderView_Previews рдХреА рд╕рдВрд░рдЪрдирд╛ рдХреЛ рдареАрдХ рдХрд░реЗрдВ:
struct HeaderView_Previews: PreviewProvider { static var previews: some View { HeaderView(section: UserData().latinities[0]) } }
рдЕрдм
QuoteView.swift рдХреЗ рд╕рдорд╛рди рдкрд░рд┐рд╡рд░реНрддрди рдХрд░реЗрдВ:
struct QuoteView_Previews: PreviewProvider { static var previews: some View { QuoteView(quote: UserData().latinities[0].quotes[0]) } }
ContentView.swift рдлрд╝рд╛рдЗрд▓ рдЦреЛрд▓реЗрдВ рдФрд░ рдЗрд╕реЗ
рд╢рд░реАрд░ рдХреА рдШреЛрд╖рдгрд╛ рд╕реЗ рдкрд╣рд▓реЗ рдЬреЛрдбрд╝реЗрдВ
@ObservedObject var userData = UserData()
рдкрд░рд┐рджреГрд╢реНрдп рдХреЛ рдкреБрдирд░реНрдЬреАрд╡рд┐рдд рдХрд░реЗрдВ
рд╕рд╛рдордЧреНрд░реА рдкрд░ рд╡рд╛рдкрд╕ рдЬрд╛рдПрдВ ContentView.swiftред ContenView рд╕рдВрд░рдЪрдирд╛ рдХреЗ рдЕрдВрджрд░, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛рдбреЗрдЯрд╛ рдкрд░рд┐рднрд╛рд╖рд╛ рдХреЗ рддреБрд░рдВрдд рдмрд╛рдж, рджреЛ рдХрд╛рд░реНрдп рдЬреЛрдбрд╝реЗрдВ:
func sectionIndex(section : SectionDataModel) -> Int { userData.latinities.firstIndex(where: {$0.letter == section.letter})! } func quoteIndex(section : Int, quote : QuoteDataModel) -> Int { return userData.latinities[section].quotes.firstIndex(where: {$0.latin == quote.latin})! }
рдЙрд╕ рдЕрдиреБрднрд╛рдЧ рд╣реЗрдбрд░ рдФрд░ рд╕реЗрд▓ рдореЗрдВ
onTapGesture рд╕рдВрд╢реЛрдзрдХ рдЬреЛрдбрд╝реЗрдВ рдЬреЛ рд╣рдо рдмрдирд╛ рд░рд╣реЗ рд╣реИрдВред
рд╢рд░реАрд░ рдХреА рд╕рд╛рдордЧреНрд░реА рдХрд╛ рдЕрдВрддрд┐рдо рджреГрд╢реНрдп:
var body: some View { List { ForEach(userData.latinities) { section in Section(header: HeaderView(section: section) .onTapGesture { self.userData.latinities[self.sectionIndex(section: section)].expanded.toggle() }, footer: EmptyView()) { if section.expanded { ForEach(section.quotes) { quote in QuoteView(quote: quote) .onTapGesture { let sectionIndex = self.sectionIndex(section: section) let quoteIndex = self.quoteIndex(section: sectionIndex, quote: quote) self.userData.latinities[sectionIndex].quotes[quoteIndex].expanded.toggle() } } } } } } .listStyle(GroupedListStyle()) }
SectionIndex рдФрд░
quotUndex рдлрд╝рдВрдХреНрд╢рдВрд╕ рдЙрди рдЦрдВрдбреЛрдВ рдФрд░ рдЙрдирдХреЗ рдкрд╛рд╕ рджрд┐рдП рдЧрдП рднрд╛рд╡реЛрдВ рдХреЗ рд╕реВрдЪрдХрд╛рдВрдХ рдХреЛ рд▓реМрдЯрд╛рддреЗ рд╣реИрдВред рдЗрди рдЕрдиреБрдХреНрд░рдореЛрдВ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рдЕрдкрдиреЗ рд╕рд░рдгреА рдХреЗ
рд▓реИрдЯрд┐рди рдореЗрдВ
рд╡рд┐рд╕реНрддрд╛рд░рд┐рдд рдЧреБрдгреЛрдВ рдХреЗ рдореВрд▓реНрдпреЛрдВ рдХреЛ
рдмрджрд▓рддреЗ рд╣реИрдВ , рдЬреЛ рдЦрдВрдб рдпрд╛ рдЕрднрд┐рд╡реНрдпрдХреНрддрд┐ рдХреЗ рддрд╣ / рдЦреБрд▓рд╛рд╕рд╛ рдХреА рдУрд░ рдЬрд╛рддрд╛ рд╣реИред

рдирд┐рд╖реНрдХрд░реНрд╖
рддреИрдпрд╛рд░ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдХреЛ
рдпрд╣рд╛рдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛
рд╣реИ ред
рдХреБрдЫ рдЙрдкрдпреЛрдЧреА рд▓рд┐рдВрдХ:
рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдкреНрд░рдХрд╛рд╢рди рдЖрдкрдХреЗ рд▓рд┐рдП рдЙрдкрдпреЛрдЧреА рд╣реЛрдЧрд╛!