[TIL]04.17
UIKETと一緒に使うSWIFTUI
SWIFTUIからUIViewを追加します。
UIViewRepresentable Protoclを使用する必要があります
UIViewRepresentableに準拠した構造を作成し、直ちにSWIFTUIで使用します.
この構造は、2つの方法を実装する必要があります.
final class RedLabel: UILabel {
override func awakeFromNib() {
super.awakeFromNib()
textColor = .red
}
}
struct RepresentableRedLabel: UIViewRepresentable {
var text: String
let redLabel = RedLabel()
func makeUIView(context: Context) -> UILabel {
redLabel
}
func updateUIView(_ uiView: UILabel, context: Context) {
redLabel.text = text
}
}
struct ContentView: View {
var body: some View {
RepresentableRedLabel(text: "내용")
}
}
// UILabel의 RedLabel을 SwiftUI에서 사용하는 경우입니다.
SWIFTUIからUI ViewControlを追加
SWIFTUIでUI ViewControllerを使用するには、UI ViewController Representableが必要です.
UIViewControllerRepresentableを実装するには、2つの方法が必要です.
– func makeUIViewController(context: Context) -> some UIViewController
– func updateUIViewController(_ uiViewController: some UIViewController, context: Context)
struct ImagePickerController: UIViewControllerRepresentable {
func makeUIViewController(context: Context) -> UIImagePickerController{
UIImagePickerController()
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
}
struct ContentView: View {
var body: some View {
ImagePickerController()
}
}
Coordinatorを使用してSWIFTUIにUI画像を表示するコードstruct ImagePickerController: UIViewControllerRepresentable {
// SwiftUI 에서의 부모뷰의 @State property부터의 Binding
@Binding var selectedImage: Image?
@Binding var existSelectedImage: Bool
func makeUIViewController(context: Context) -> UIImagePickerController {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = context.coordinator
return imagePickerController
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {}
// Cordinator 대입.
func makeCoordinator() -> Coordinator {
Coordinator(selectedImage: $selectedImage, existSelectedImage: $existSelectedImage)
}
}
extension ImagePickerController {
// Cordinator 만들기
final class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
@Binding var selectedImage: Image?
@Binding var existSelectedImage: Bool
// 밑줄을 사용해서 초기화 해야한다. 프로퍼티 래퍼임을 알려주기 위해서.
init(selectedImage: Binding<Image?>, existSelectedImage: Binding<Bool>) {
_selectedImage = selectedImage
_existSelectedImage = existSelectedImage
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
guard let selectedOriginalImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage else { return }
selectedImage = Image(uiImage: selectedOriginalImage)
existSelectedImage = true
}
}
}
struct ContentView: View {
@State private var selectedImage: Image?
@State private var existSelectedImage = false
var body: some View {
ZStack {
VStack {
selectedImage?
.resizable()
.aspectRatio(contentMode: .fit)
.frame(width: 100.0, height: 100.0)
Button(action: didTapSelectedImageButton) {
Text("Select Image")
}
}
if selectedImage == nil {
ImagePickerController(
selectedImage: $selectedImage,
existSelectedImage: $existSelectedImage
)
}
}
}
private func didTapSelectedImageButton() {
selectedImage = nil
existSelectedImage = false
}
}
// @State property와 Binding으로 Coordinator에서 부모 뷰에 업데이트를 별도로 하지 않아도 간단하게 구현함
既存のUIViewまたはUIViewControllerでSWIFTUI Viewを使用する場合、UIViewRepresentableに準拠するStructを個別に作成する必要がない場合は、UImit classでExtensionインプリメンテーションを使用できます.final class Label: UILabel {}
// Extension 으로 정의
extension Label: UIViewRepresentable {
func makeUIView(context: Context) -> UILabel {
backgroundColor = .gray
text = "This is UIKit UILabel"
return self
}
func updateUIView(_ uiView: UILabel, context: Context) {}
}
struct ContentView: View {
var body: some View {
VStack {
Text("This is Swift UI Text")
Label()
}
}
}
UIKETからSWIFTUIを追加します。
UIHosting Controlを使用する必要があります.
メソッドやプロパティを追加する必要はありません.
UI HostingController(RootView:UIキットに表示されるSwitUI):SwitUIビューを初期化して挿入すると終了します
struct ContentView: View {
var body: some View {
Text("내용")
.fontWeight(.bold)
}
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let hostingController = UIHostingController(rootView: ContentView())
hostingController.view.translatesAutoresizingMaskIntoConstraints = false
hostingController.view.frame = view.bounds
addChild(hostingController)
view.addSubview(hostingController.view)
}
}
UI HostingControllerのrootViewにSwitUIを入れるだけです.addChild、addSubViewは、これまでUIツールパッケージにUI ViewControlを追加したときと同じです.struct ContentView: View {
var body: some View {
Text("펭 - 하!")
.fontWeight(.bold)
}
}
class ViewController: UIViewController {
@IBAction private func didTapPresentButton(_ sender: Any) {
let hostingController = UIHostingController(rootView: ContentView())
present(hostingController, animated: true)
}
}
SWIFTUI画面を表示する場合、SWIFTUIビューをUI Hosting Controllerでラップする以外、他のUIキットコードは常に使用できます.SWIFTUIビューを変数として他のビュー構造に渡します。
@ViewBuilderの使用
struct ContainerView<Content: View>: View {
@ViewBuilder var content: Content
var body: some View {
content
}
}
// 뷰에 단순히 넣는것 뿐만 아니라, if-else, switch-case 블럭에서도 사용 가능하다.
struct SimpleView: View {
var body: some View {
ContainerView{
Text("SimpleView Text")
}
}
}
struct IfElseView: View{
var flag = true
var body: some View {
ContainerView{
if flag {
Text("True text")
} else {
Text("False text")
}
}
}
}
struct SwitchCaseView: View {
var condition = 1
var body: some View {
ContainerView {
switch condition {
case 1:
Text("one")
default:
Text("Default")
}
}
}
}
ジェニーリックと頭文字でログインする方法
struct ParentView: View {
var body: some View {
NavigationView{
VStack(spacing: 8){
ChildView(destinationView: Text("View1"), title: "1st")
ChildView(destinationView: Text("View2"), title: "2nd")
Spacer()
}
.padding(.all)
.navigationBarTitle("NavigationLinks")
}
}
}
struct ChildView<Content: View>: View {
var destinationView: Content
var title: String
init(destinationView: Content, title: String) {
self.destinationView = destinationView
self.title = title
}
var body: some View {
NavigationLink(destination: destinationView){
Text("This item opens the \(title) view").foregroundColor(Color.black)
}
}
}
SwiftUI | List (UITableView)
SWIFTUIではUITableViewがListです.
List
UIKETのUITAbleViewDelegateやUITAbleViewDataSourceを使わずに簡単に実現できます.
struct ContentView: View {
var body: some View {
List {
Text("1")
Text("2")
Text("3")
}
}
}
追加アイテムのカスタマイズも簡単ですstruct CustomCell: View {
var body: some View {
HStack {
Image(systemName: "tortoise.fill")
Text("거북이")
}
}
}
struct ContentView: View {
var body: some View {
List {
CustomCell()
Text("1")
Text("2")
Text("3")
}
}
}
リストがナビゲーションビューのサブビューとして宣言され、Cellがナビゲーションリンクによって囲まれている場合、Cellをタッチすることによって他のビューに移動することができる.アレイ内のデータをListとして表示する
リストに表示されるArrayの内容は、Identificalプロトコルに従うclass、structとして定義する必要があります.
struct Item: Identifiable {
var id = UUID() // Int, String 등 hashable을 따르는 것들은 뭐든지 가능
let name: String
}
必ずリスト内で認識できるid propertyが必要!struct ContentView: View {
let items: [Item] = [Item(name: "asdf"), Item(name: "sadfasf")]
var body: some View {
NavigationView {
List(items) {item in
Text(item.name)
}
.listStyle(GroupedListStyle())
.navigationBarTitle("List View")
}
}
}
削除リスト項目の変更
まずitemsはステータスpropertyとして存在しなければならない.したがって、上記のコードのitemsを
@State private var items
に変換し、次のコードのように関数を追加することができる.List {
// ForEach로 각각의 cell에 delete 메소드를 입력시켜주어야한다.
ForEach(items) { item in
Text(item.name)
}.onDelete(perform: didDeleteCell)
}
.listStyle(GroupedListStyle())
.navigationBarTitle("List View")
// parameter 에는 반드시 offsets 을 추가해야 함.
func didDeleteCell(at offsets: IndexSet) {
items.remove(atOffsets: offsets)
print("Deleted cell is \(offsets)")
}
コードの変更(セルの順序を変更可能)List {
ForEach(items) { item in
Text(item.name)
}.onMove(perform: didMoveCell)
}
.listStyle(GroupedListStyle())
.navigationBarTitle("List View")
.navigationBarItems(trailing: EditButton()) // 수정 버튼이 들어갈 Item
func didMoveCell(form source: IndexSet, to destination: Int) {}
リファレンスhttps://unnnyong.com/2020/05/23/swiftui-uikit-%ea%b3%bc-%ed%95%a8%ea%bb%98-%ec%82%ac%ec%9a%a9%ed%95%98%ea%b8%b0-uiviewrepresentable-uiviewcontrollerrepresentable-uihostingcontroller/#comment-25
https://stackoverflow.com/questions/56938805/how-to-pass-one-swiftui-view-as-a-variable-to-another-view-struct?rq=1
https://unnnyong.com/2020/05/22/swiftui-list-%ea%b5%ac-uitableview/
Reference
この問題について([TIL]04.17), 我々は、より多くの情報をここで見つけました https://velog.io/@rbw/TIL04.17テキストは自由に共有またはコピーできます。ただし、このドキュメントのURLは参考URLとして残しておいてください。
Collection and Share based on the CC Protocol