У меня вопрос. Я пытаюсь создать небольшое приложение, в котором я отправляю запрос POST с изображением в API. Я поместил все свои сетевые logi c в отдельный быстрый класс, и у меня есть главный контроллер представления. Проблема, с которой я столкнулся, заключается в том, что мне нужно получить изображение из моего основного контроллера просмотра и отправить его в отдельный сетевой класс, чтобы его можно было отправить с помощью POST REQUEST, но у меня возникли проблемы с этим, поскольку значение изображения возвращает ноль при передаче в сетевой класс. Я пробовал использовать замыкания, делегаты, свойства, чтобы попытаться передать это изображение, но безуспешно. Если я делаю всю сеть в своем основном контроллере просмотра, все работает нормально, но я хотел бы отделить сетевой лог c. Я занимаюсь этим в течение двух дней, ПОЖАЛУЙСТА, помогите подсказать, что мне не хватает, или лучший способ go об этом.
import UIKit
import YPImagePicker
class NewViewController: UIViewController {
static let instance = NewViewController()
var config = YPImagePickerConfiguration()
override func viewDidLoad() {
super.viewDidLoad()
config.isScrollToChangeModesEnabled = true
config.onlySquareImagesFromCamera = true
config.usesFrontCamera = false
config.showsPhotoFilters = false
config.showsVideoTrimmer = true
config.shouldSaveNewPicturesToAlbum = true
config.albumName = "DefaultYPImagePickerAlbumName"
config.startOnScreen = YPPickerScreen.photo
config.screens = [.library, .photo]
config.showsCrop = .none
config.targetImageSize = YPImageSize.original
config.overlayView = UIView()
config.hidesStatusBar = true
config.hidesBottomBar = false
config.preferredStatusBarStyle = UIStatusBarStyle.default
config.bottomMenuItemSelectedTextColour = UIColor()
config.bottomMenuItemUnSelectedTextColour = UIColor()
// config.filters = [DefaultYPFilters...]
config.maxCameraZoomFactor = 1.0
// Do any additional setup after loading the view.
}
@IBOutlet weak var imageView: UIImageView!
@IBAction func sendBtn(_ sender: UIButton) {
NetworkServices.instance.userChoice { (Age) in
print(Age)
}
}
@IBAction func imageBtn(_ sender: UIButton) {
let picker = YPImagePicker(configuration: config)
picker.didFinishPicking { [unowned picker] items, _ in
if let photo = items.singlePhoto {
self.imageView.contentMode = .scaleToFill
self.imageView.image = photo.originalImage
}
picker.dismiss(animated: true, completion: nil)
}
present(picker, animated: true, completion: nil)
}
func getimages(completion: @escaping(UIImage) -> ()) {
completion(imageView.image!) // THIS IS WHERE I USED CLOSURES TO SEND MY IMAGE.
}
}
// Ниже приведен мой сетевой класс, который использует метод POST, метод post работает, но этот класс // никогда не получает изображение из основного класса контроллера просмотра.
import UIKit
typealias Parameters = [String: String]
class NetworkServices {
static let instance = NetworkServices()
func userChoice(completion: @escaping (Float) -> ()) {
NewViewController.instance.getimages { (image) in
guard let mediaImage = Media(withImage: image , forKey: "inputFile") else { return } //This is where you manually change things, insert your image and the key
guard let url = URL(string: "https://api.cloudmersive.com/image/face/detect-age") else { return }
var request = URLRequest(url: url)
request.httpMethod = "POST"
let boundary = self.generateBoundary()
request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")
request.addValue("f6-4e94-8b-e4f1", forHTTPHeaderField: "Apikey")
let dataBody = self.createDataBody(withParameters: nil, media: [mediaImage], boundary: boundary)
request.httpBody = dataBody
let task = URLSession.shared.dataTask(with: request) { (data, response, error) in
if error != nil{
debugPrint("Errors were found")
return
}
guard let data = data else{ return }
do {
guard let json = try JSONSerialization.jsonObject(with: data, options: [.allowFragments]) as? [String: Any] else { return }
guard let outputs = json["PeopleWithAge"] as? [[String: Any]] else { return }
var requiredAge = [Float]()
for ages in outputs {
let age = ages["Age"] as? Float ?? 0.0
requiredAge.append(age)
DispatchQueue.main.async {
completion(age)
}
}
} catch {
debugPrint("JSON error: \(error.localizedDescription)")
}
}
task.resume()
}
}
//MARK: - Post Methods
func generateBoundary() -> String {
return "Boundary-\(NSUUID().uuidString)"
}
func createDataBody(withParameters params: Parameters?, media: [Media]?, boundary: String) -> Data {
let lineBreak = "\r\n" //this is required in converting my file into data
var body = Data()
if let parameters = params {
for (key, value) in parameters {
body.append("--\(boundary + lineBreak)")
body.append("Content-Disposition: form-data; name=\"\(key)\"\(lineBreak + lineBreak)")
body.append("\(value + lineBreak)")
}
}
if let media = media {// put in your filename here from media class
for photo in media {
body.append("--\(boundary + lineBreak)")
body.append("Content-Disposition: form-data; name=\"\(photo.key)\"; filename=\"\(photo.filename)\"\(lineBreak)")
body.append("Content-Type: \(photo.mimeType + lineBreak + lineBreak)")
body.append(photo.data)// append actual image from Media class when you initialise Media class
body.append(lineBreak)
}
}
body.append("--\(boundary)--\(lineBreak)")
return body
}
}
extension Data {
mutating func append(_ string: String) { // i will use this to append all my files.
if let data = string.data(using: .utf8) {
append(data)
}
}
}