我想做的是拍攝一張圖片,將其編碼為base64,然后將其放在一個字典中發送到我的服務器。當我把字典發送過去時,有時它帶著 base64 發送,有時不帶,即使我沒有做任何改動。 下面是相機視圖的代碼
struct CameraView。View {
@StateObject var camera = CameraModel()
var body。some View {
ZStack {
CameraPreview(camera: 攝像頭)
.ignoresSafeArea(.all, edges: .all)
VStack{
if camera.isTaken{
HStack{
Spacer()
Button(action: camera.retake, label: {
Image(systemName: "arrow.triangle.2.circlepath.camera")
.foregroundColor(.black)
.padding()
.background(Color.white)
.clipShape(Circle())
})
.padding(.trailing, 10)
}
}
Spacer()
HStack{
if camera.isTaken{
Button(action: camera.sendPicData , label: {
Text("Save"/span>)
.foregroundColor(.black)
.fontWeight(.semibold)
.padding(.vertical, 10)
.padding(.horizontal, 10)
.background(Color.white)
.clipShape(Capsule())
})
.padding(.leading)
Spacer()
}
else{
Button(action: camera.takePic, label: {
ZStack{
Circle()
.填充(Color.white)
.框架(寬度:65,高度。65)
Circle()
.stroke(Color.white, lineWidth: 2)
.frame(width: 75, height: 75)
}
})
}
}
.frame(高度: 75)
}
}
.onAppear(執行。{
camera.Check()
})
}
}
struct CameraPreview: UIViewRepresentable{
@ObservedObject var camera: CameraModel
func makeUIView(context: Context) -> UIView {
let view = UIView( frame: UIScreen.main.bounds)
camera.preview = AVCaptureVideoPreviewLayer(session: camera.session)
camera.preview.frame = view.frame
camera.preview.videoGravity = .resizeAspectFill
view.layer.addSublayer(camera.preview)
攝像機.session.startRunning()
return view
}
func updateUIView(_ uiView: UIView, context: Context) {
}
}
以及拍攝圖片并將其發送到服務器的代碼
class CameraModel: NSObject, ObservableObject, AVCapturePhotoCaptureDelegate{
var isTaken = false
var alert = false
var sendPic = false
var session = AVCaptureSession()
var output = AVCapturePhotoOutput()
var preview: AVCaptureVideoPreviewLayer!
var picData = Data(count: 0)
func Check(){
switch AVCaptureDevice.authorizationStatus(for: .video) {
case .authorized:
SetUp()
return
case .notDetermined:
AVCaptureDevice.requestAccess(for: .video) { (status) in.
if status{
self.setUp()
}
}
case .denied:
self.alert.toggle()
回傳。
default:
}
}
func setUp(){
do{
self.session.beginConfiguration()
let device = AVCaptureDevice.default(.biltInWideAngleCamera, for: .video, position: .back)
let input = try AVCaptureDeviceInput(device: device!)
if self.session.canAddInput(input){
self.session.addInput(input)
}
if self.session.canAddOutput(self.output){
self.session.addOutput(self.output)
}
self.session.commitConfiguration()
}
catch{
print(error.localizedDescription)
}
}
func takePic(){
DispatchQueue.global(qos: .background).async {
self.output.capturePhoto(with: AVCapturePhotoSettings(), delegate: self)
self.session.stopRunning()
DispatchQueue.main.async {
withAnimation{self.isTaken.toggle()}。
}
print("pic taken..."/span>)
}
}
func retake(){
DispatchQueue.global(qos: .background).async {
self.session.startRunning()
DispatchQueue.main.async {
withAnimation{self.isTaken.toggle()}。
}
}
}
func photoOutput(_ output: AVCapturePhotoOutput, didFinishProcessingPhoto photo: AVCapturePhoto, error: Error?) {
if error != nil{
return
}
guard let imageData = photo.fileDataRepresentation() else{return }
self.picData = imageData
}
func sendPicData(){
let image = UIImage(data: self.picData)
let imageData: Data = image?。 jpegData(compressionQuality: 0.1) ? Data()
let imageString: String = imageData.base64EncodedString()
let dictionary:[String:String] = ["Dot"/span>:imageString]
if let theJSONData = try? JSONSerialization.data(withJSONObject: dictionary, options: [.prettyPrinted] ) {
guard let sendURL = URL(字串。 "http://toServer") else {
print("無效的URL")
回傳。
}
var request = URLRequest(url: sendURL)
request.setValue("application/json"/span>, forHTTPHeaderField: "Content-Type")
request.setValue("application/json", forHTTPHeaderField: "接受")
request.httpMethod = "POST"。
request.httpBody = theJSONData
URLSession.shared.dataTask(with: request) {data, response, error in
guard data != nil else {
print ("PUT Failed: (error?.localizedDescription ? "未知錯誤"))
return。
}
}.resume()
print(dictionary)
}
}
}
我不知道為什么它是如此不一致的。這對我來說沒有任何意義,如果它一次成功,為什么不是每次都能成功?請幫助我們
。uj5u.com熱心網友回復:
問題是委托函式func photoOutput()并不是在每次拍攝照片時都被呼叫。我發現在func takePic()中,如果我在self.session.stopRunning()上放置一個Timer,它將解決這個問題并每次都呼叫委托函式,但它也會導致另一個問題,即停止呼叫self.isTaken.toggle()。為了解決這個問題,我把Timer放在DispatchQueue.main.async中,就像這樣
func takePic(){
DispatchQueue.global(qos: .background).async {
self.output.capturePhoto(with: AVCapturePhotoSettings(), delegate: self)
DispatchQueue.main.async {
Timer.scheduledTimer(withTimeInterval: 0.1, repeats: false) { (timer) in
self.session.stopRunning()
}
}
DispatchQueue.main.async {
withAnimation{self.isTaken.toggle()}。
}
print("pic taken..."/span>)
}
}
我不確定這是否是解決這個問題的最佳方法,但我看到很多人都有相同的類似問題,用這個方案每次都會呼叫委托函式。
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/320471.html
標籤:
