SwiftUI / добавить фото в круг

Когда выкладываю фото как видно на картинке, то такое же фото выходит в 3-х кругах.

Я хочу добавлять в каждый круг отдельные фотографии, поэтому добавляю их с камеры или галереи с помощью созданного селектора. Однако код, который я сделал, может быть неправильным, можете ли вы показать правильную логику? У меня недостаточно информации, чтобы исправить это, извините.

struct SendPicture: View {
    @State private var image: Image? = Image("plus")
    @State private var shouldPresentImagePicker = false
    @State private var shouldPresentActionScheet = false
    @State private var shouldPresentCamera = false
    
    var body: some View {
        GeometryReader{ geometry in
            VStack{
                HStack{
                    Text("Picture")
                    .font(.system(size: 60))
                    .frame(width:geometry.size.width, height: geometry.size.height / 10)
                    .foregroundColor(.init(red: 45/255, green: 0/255, blue: 112/255))
                    Spacer().frame(height: geometry.size.height / 5)
                }
                
                VStack{
                    Text("Hi").frame(width:geometry.size.width, height: geometry.size.height / 10)
                    
                }
                VStack{
                    Image("AstroGirl").resizable()
                    .aspectRatio(contentMode: .fit)
                    .frame(width: geometry.size.width,height: geometry.size.height / 3)
                    
                }
                HStack{
                    image!
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: geometry.size.width / 5, height: geometry.size.height / 10)
                    .clipShape(Circle())
                    .overlay(Circle().stroke(Color.yellow, lineWidth: 4))
                    .shadow(radius: 10)
                    .onTapGesture { self.shouldPresentActionScheet = true }
                    .sheet(isPresented: $shouldPresentImagePicker) {
                        SUImagePickerView(sourceType: self.shouldPresentCamera ? .camera : .photoLibrary, image: self.$image, isPresented: self.$shouldPresentImagePicker)
                    }.actionSheet(isPresented: $shouldPresentActionScheet) { () -> ActionSheet in
                        ActionSheet(title: Text("Choose mode"), message: Text("Please choose your preferred mode to set your profile image"), buttons: [ActionSheet.Button.default(Text("Camera"), action: {
                            self.shouldPresentImagePicker = true
                            self.shouldPresentCamera = true
                        }), ActionSheet.Button.default(Text("Photo Library"), action: {
                            self.shouldPresentImagePicker = true
                            self.shouldPresentCamera = false
                        }), ActionSheet.Button.cancel()])
                    }
                    image!
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: geometry.size.width / 5, height: geometry.size.height / 10)
                    .clipShape(Circle())
                    .overlay(Circle().stroke(Color.yellow, lineWidth: 4))
                    .shadow(radius: 10)
                    .onTapGesture { self.shouldPresentActionScheet = true }
                    .sheet(isPresented: $shouldPresentImagePicker) {
                        SUImagePickerView(sourceType: self.shouldPresentCamera ? .camera : .photoLibrary, image: self.$image, isPresented: self.$shouldPresentImagePicker)
                    }.actionSheet(isPresented: $shouldPresentActionScheet) { () -> ActionSheet in
                        ActionSheet(title: Text("Choose mode"), message: Text("Please choose your preferred mode to set your profile image"), buttons: [ActionSheet.Button.default(Text("Camera"), action: {
                            self.shouldPresentImagePicker = true
                            self.shouldPresentCamera = true
                        }), ActionSheet.Button.default(Text("Photo Library"), action: {
                            self.shouldPresentImagePicker = true
                            self.shouldPresentCamera = false
                        }), ActionSheet.Button.cancel()])
                    }
                    image!
                    .resizable()
                    .aspectRatio(contentMode: .fill)
                    .frame(width: geometry.size.width / 5, height: geometry.size.height / 10)
                    .clipShape(Circle())
                    .overlay(Circle().stroke(Color.yellow, lineWidth: 4))
                    .shadow(radius: 10)
                    .onTapGesture { self.shouldPresentActionScheet = true }
                    .sheet(isPresented: $shouldPresentImagePicker) {
                        SUImagePickerView(sourceType: self.shouldPresentCamera ? .camera : .photoLibrary, image: self.$image, isPresented: self.$shouldPresentImagePicker)
                    }.actionSheet(isPresented: $shouldPresentActionScheet) { () -> ActionSheet in
                        ActionSheet(title: Text("Choose mode"), message: Text("Please choose your preferred mode to set your profile image"), buttons: [ActionSheet.Button.default(Text("Camera"), action: {
                            self.shouldPresentImagePicker = true
                            self.shouldPresentCamera = true
                        }), ActionSheet.Button.default(Text("Photo Library"), action: {
                            self.shouldPresentImagePicker = true
                            self.shouldPresentCamera = false
                        }), ActionSheet.Button.cancel()])
                    }
                }
                Spacer().frame(height: geometry.size.height / 10)
                VStack{
                    Button(action: {
                        
                    }, label: {
                        Text("Giriş Yap")
                        .frame(width: geometry.size.width / 3, height: 50)
                        .padding(10)
                        .font(Font.system(size: 30, weight: .medium, design: .serif))
                        .foregroundColor(.white)
                        .background(RoundedRectangle(cornerRadius: 30))
                        .foregroundColor(.init(red: 45/255, green: 0/255, blue: 112/255))
                        
                    })
                }
            }
        }
    }
}
import SwiftUI
import UIKit

struct SUImagePickerView: UIViewControllerRepresentable {
    
    var sourceType: UIImagePickerController.SourceType = .photoLibrary
    @Binding var image: Image?
    @Binding var isPresented: Bool
    
    func makeCoordinator() -> ImagePickerViewCoordinator {
        return ImagePickerViewCoordinator(image: $image, isPresented: $isPresented)
    }
    
    func makeUIViewController(context: Context) -> UIImagePickerController {
        let pickerController = UIImagePickerController()
        pickerController.sourceType = sourceType
        pickerController.delegate = context.coordinator
        return pickerController
    }
    
    func updateUIViewController(_ uiViewController: UIImagePickerController, context: Context) {
        // Nothing to update here
    }
}

class ImagePickerViewCoordinator: NSObject, UINavigationControllerDelegate,
UIImagePickerControllerDelegate {
    
    @Binding var image: Image?
    @Binding var isPresented: Bool
    
    init(image: Binding<Image?>, isPresented: Binding<Bool>) {
        self._image = image
        self._isPresented = isPresented
    }
    
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            self.image = Image(uiImage: image)
        }
        self.isPresented = false
    }
    
    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        self.isPresented = false
    }
}

Это гораздо яснее, чем ваш предыдущий вопрос. Хорошая работа!

aheze 25.12.2020 22:00

Я только изучаю SwiftUI, но мне кажется, что вы используете одни и те же переменные @State для всех 3 изображений. Бьюсь об заклад, все 3 замыкания срабатывают и устанавливают выбранное изображение во всех 3 представлениях изображения. Попробуйте настроить отдельные переменные состояния для каждой иконки. Я бы также написал общие функции для настройки средства выбора и листа и вызывал их из действия касания каждого значка. Это позволит избежать дублирования кода.

Duncan C 25.12.2020 22:20

@DuncanC Да, вот и все. ОП трижды передает одно и то же изображение, как в image: self.$image. Вы были первым, так что не стесняйтесь писать это как ответ.

pawello2222 25.12.2020 22:30

@DuncanC Я сделал то, что ты сказал, но не смог это исправить.

GurkanEsen 25.12.2020 22:35

Если у вас есть время, можете ли вы получить эти коды и попробовать сами?

GurkanEsen 25.12.2020 22:38

мой английский плохой, извините, я пытаюсь побороть :) @aheze

GurkanEsen 25.12.2020 22:40
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
3
6
1 026
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я только изучаю SwiftUI, но мне кажется, что вы используете одни и те же переменные @State для всех 3 изображений. Бьюсь об заклад, все 3 замыкания срабатывают и устанавливают выбранное изображение во всех 3 представлениях изображения.

Попробуйте настроить отдельные переменные состояния для каждой иконки. Я бы также написал общие функции для настройки средства выбора и листа и вызывал их из действия касания каждого значка. Это позволит избежать дублирования кода.

Если вы загрузите рабочий проект или игровую площадку SwiftUI на Github, опубликуйте ссылку, и мы постараемся показать вам, как это исправить. (Я в невыгодном положении, так как я только начал изучать SwiftUI на прошлой неделе, но я занимаюсь разработкой для iOS уже несколько лет.)

Извините, я не знаю с Github. @Дункан С

GurkanEsen 25.12.2020 23:52
Ответ принят как подходящий

Как заметил Дункан С., вы используете одно и то же свойство @State для всех просмотров изображений.

Возможное решение — извлечь повторяющийся код в новое представление:

struct IconView: View {
    @State private var image: Image?
    @State private var shouldPresentImagePicker = false
    @State private var shouldPresentActionScheet = false
    @State private var shouldPresentCamera = false

    var imageView: Image {
        image ?? Image("plus")
    }

    var body: some View {
        imageView
            .resizable()
            .aspectRatio(contentMode: .fill)
            .clipShape(Circle())
            .overlay(Circle().stroke(Color.yellow, lineWidth: 4))
            .onTapGesture { self.shouldPresentActionScheet = true }
            .sheet(isPresented: $shouldPresentImagePicker) {
                SUImagePickerView(sourceType: self.shouldPresentCamera ? .camera : .photoLibrary, image: self.$image, isPresented: self.$shouldPresentImagePicker)
            }
            .actionSheet(isPresented: $shouldPresentActionScheet) { () -> ActionSheet in
                ActionSheet(title: Text("Choose mode"), message: Text("Please choose your preferred mode to set your profile image"), buttons: [ActionSheet.Button.default(Text("Camera"), action: {
                    self.shouldPresentImagePicker = true
                    self.shouldPresentCamera = true
                }), ActionSheet.Button.default(Text("Photo Library"), action: {
                    self.shouldPresentImagePicker = true
                    self.shouldPresentCamera = false
                }), ActionSheet.Button.cancel()])
            }
    }
}

а затем используйте это представление в своем HStack:

struct SendPicture: View {
    var body: some View {
        GeometryReader { geometry in
            VStack {
                ...
                HStack {
                    ForEach(0 ..< 3) { _ in
                        IconView()
                            .frame(width: geometry.size.width / 5, height: geometry.size.height / 10)
                            .shadow(radius: 10)
                    }
                }
                ...
            }
        }
    }
}

Весь вид SendPicture будет выглядеть так:

struct SendPicture: View {
    var body: some View {
        GeometryReader { geometry in
            VStack {
                HStack {
                    Text("Picture")
                        .font(.system(size: 60))
                        .frame(width: geometry.size.width, height: geometry.size.height / 10)
                        .foregroundColor(.init(red: 45 / 255, green: 0 / 255, blue: 112 / 255))
                    Spacer().frame(height: geometry.size.height / 5)
                }

                VStack {
                    Text("Hi").frame(width: geometry.size.width, height: geometry.size.height / 10)
                }
                VStack {
                    Image("AstroGirl").resizable()
                        .aspectRatio(contentMode: .fit)
                        .frame(width: geometry.size.width, height: geometry.size.height / 3)
                }
                // This `HStack` is changed
                HStack {
                    ForEach(0 ..< 3) { _ in
                        IconView()
                            .frame(width: geometry.size.width / 5, height: geometry.size.height / 10)
                            .shadow(radius: 10)
                    }
                }
                Spacer().frame(height: geometry.size.height / 10)
                VStack {
                    Button(action: {}, label: {
                        Text("Giriş Yap")
                            .frame(width: geometry.size.width / 3, height: 50)
                            .padding(10)
                            .font(Font.system(size: 30, weight: .medium, design: .serif))
                            .foregroundColor(.white)
                            .background(RoundedRectangle(cornerRadius: 30))
                            .foregroundColor(.init(red: 45 / 255, green: 0 / 255, blue: 112 / 255))

                    })
                }
            }
        }
    }
}

Я не мог совместить эти коды с кодами, которые я написал. Не могли бы вы справиться с этим. @pawello2222

GurkanEsen 26.12.2020 00:17

@GurkanEsen Хорошо, я добавил полный код просмотра SendPicture.

pawello2222 26.12.2020 00:21

Работал. большой :)

GurkanEsen 26.12.2020 00:30

Другие вопросы по теме