I had the same problem, but there are some differences, however I think you can use this solution.
First, add an extension to detect image orientation. It's not mandatory, you can use a local function or ternary operator directly into the view modifier of rotation effect.
import SwiftUI
extension UIImage {
func getRotationAngle() -> Angle {
switch imageOrientation {
case .left:
return Angle(degrees: 270)
case .leftMirrored:
return Angle(degrees: 270)
case .right:
return Angle(degrees: 90)
case .rightMirrored:
return Angle(degrees: 90)
case .down:
return Angle(degrees: 180)
case .downMirrored:
return Angle(degrees: 180)
default:
return Angle(degrees: 0)
}
}
}
Then You need to get the UIImage. For that You can use this image picker or your alternative is perfect too.
import SwiftUI
struct ImagePicker: UIViewControllerRepresentable {
@Binding var image: UIImage?
@Binding var imageURL: URL?
@Environment(\.presentationMode) var presentationMode
class Coordinator: NSObject, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
let parent: ImagePicker
init(_ parent: ImagePicker) {
self.parent = parent
}
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
if let uiImage = info[.originalImage] as? UIImage {
parent.image = uiImage
}
if let imageURL = info[.imageURL] as? URL {
parent.imageURL = imageURL
// Alternative
//let imageData = try! Data(contentsOf: url!)
//parent.image = UIImage(data: imageData)!
}
parent.presentationMode.wrappedValue.dismiss()
}
}
func makeUIViewController(context: UIViewControllerRepresentableContext<ImagePicker>) -> UIImagePickerController {
let picker = UIImagePickerController()
picker.delegate = context.coordinator
return picker
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func updateUIViewController(_ uiViewController: UIImagePickerController, context: UIViewControllerRepresentableContext<ImagePicker>) {
}
}
And here the implementation.
import SwiftUI
struct ProfileView: View {
@State private var showingImagePicker = Bool()
@State private var inputImage = UIImage(systemName: "person.crop.circle")
@State var imageURL: URL? = nil
var body: some View {
VStack(spacing: 0) {
Text("Your profile")
.foregroundColor(.white)
.font(.custom("VisbyCF-Heavy", size: 24))
.frame(maxWidth: .infinity, alignment: .leading)
.padding(.top, 37)
.padding(.bottom, 33)
VStack(spacing: 0) { // Picture
ZStack {
if #available(iOS 15.0, *) {
AsyncImage(
url: imageURL,
content: { image in
image
.resizable()
.aspectRatio(contentMode: .fill)
.frame(maxWidth: 105, maxHeight: 105)
.cornerRadius(53)
.rotationEffect(inputImage?.getRotationAngle() ?? Angle(degrees: 0))
}, placeholder: {
Image(systemName: "person.crop.circle")
.resizable()
.aspectRatio(contentMode: .fill)
.frame(maxWidth: 105, maxHeight: 105)
.cornerRadius(53)
}
)
}
ZStack {
HStack{
Image(systemName: "pencil.circle")
.resizable()
.frame(width: 12, height: 12)
.padding(5)
}
.frame(width: 24, height: 24)
.background(Color.blue)
.clipShape(Circle())
.shadow(radius: 10)
.onTapGesture {
self.showingImagePicker = true
}
}
.frame(maxWidth: 105,maxHeight: .infinity, alignment: .bottom)
.offset(x: 35)
}
.frame(width: 105, height: 105)
.padding(.bottom, 7)
Text("Change picture")
.foregroundColor(Color.white)
.font(.custom("VisbyCF-Heavy", size: 14))
.padding(.bottom, 32)
}
Spacer()
}
.padding([.leading, .trailing], 35)
.navigationBarColor(.clear)
.navigationBarTitle(Text("Your profile"), displayMode: .inline)
.sheet(isPresented: $showingImagePicker) {
ImagePicker(image: $inputImage, imageURL: $imageURL)
}
}
}Ï