从Swift文件(不是ViewController)将图像传递到ViewController

时间:2019-07-08 08:24:53

标签: ios swift

我在扩展程序中使用cropViewController来裁剪图像。结果进入一个快速文件(不是视图控制器)。但是现在需要在另一个视图控制器中设置图像。

正在使用CropViewController:https://github.com/TimOliver/TOCropViewController

我的View Controller 文件具有以下元素

import UIKit
import XLPagerTabStrip

class GetPetViewController: UIViewController, IndicatorInfoProvider {
    // Initialize Default Value
    let userDefault = UserDefaults.standard

    @IBOutlet var bPetImage: UIButton!

    @IBAction func bPetImage_TouchUpInside(_ sender: Any) {
        // Start Action Sheet
        StartImageActionSheet()
    }

    @IBAction func bSavePet_TouchUpInside(_ sender: Any) {
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        // Set The Default Value
        userDefault.set("GetPet", forKey: "senderActivity")
        userDefault.synchronize()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    // Tab Functionality
    func indicatorInfo(for pagerTabStripController: PagerTabStripViewController) -> IndicatorInfo {
        return IndicatorInfo(image: UIImage(named: "ic_get_pet"), highlightedImage: UIImage(named: "ic_get_pet"), userInfo: Any?.self)
    }
}

我的第二个文件(不是视图控制器)

import CropViewController
import FirebaseAuth
import Foundation
import SwiftyJSON
import UIKit

class ImageFunctions {
}

extension UIViewController {
    // Image Action Sheet
    func StartImageActionSheet() {
        let imagePickerController = UIImagePickerController()
        imagePickerController.delegate = self as UIImagePickerControllerDelegate & UINavigationControllerDelegate

        // Action Sheet To Select Camera Or Photo Library
        let actionSheet = UIAlertController(title: "Select Image", message: "Please Choose A Source", preferredStyle: .actionSheet)

        actionSheet.addAction(UIAlertAction(title: "Camera", style: .default, handler: {
            (_: UIAlertAction!) in

            if UIImagePickerController.isSourceTypeAvailable(.camera) {
                imagePickerController.sourceType = .camera
                self.present(imagePickerController, animated: true, completion: nil)
            } else {
                self.uiAlertControllerAction(alertTitle: "Problem With Camera", alertMessage: "Unable To Load Camera", action: "")
            }

        }))

        actionSheet.addAction(UIAlertAction(title: "Photo Library", style: .default, handler: {
            (_: UIAlertAction!) in

            imagePickerController.sourceType = .photoLibrary
            self.present(imagePickerController, animated: true, completion: nil)

        }))

        actionSheet.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
        present(actionSheet, animated: true, completion: nil)
    }

    // For Image Upload To Server Using PHP
    func myImageUploadRequest(image: UIImage) {
        // Initialize User Defaults
        let userDefault = UserDefaults.standard

        // Get The Sender Activity from User Defaults
        let senderActivityValue = userDefault.string(forKey: "senderActivity")

        let myUrl = NSURL(string: "someurl")

        let request = NSMutableURLRequest(url: myUrl! as URL)
        request.httpMethod = "POST"

        // Get The Firebase User
        guard let user = Auth.auth().currentUser else { return }

        let param = [
            "desc": user.uid,
            "sender": senderActivityValue!,
        ]

        let boundary = generateBoundaryString()

        request.setValue("multipart/form-data; boundary=\(boundary)", forHTTPHeaderField: "Content-Type")

        let imageData = image.jpegData(compressionQuality: 0.75)

        if imageData == nil { return }

        request.httpBody = createBodyWithParameters(parameters: param, filePathKey: "image", imageDataKey: imageData! as NSData, boundary: boundary) as Data

        let task = URLSession.shared.dataTask(with: request as URLRequest) {
            data, _, error in

            if error != nil {
                print("error=\(String(describing: error))")
                return
            }

            // You can print out response object
            // print("******* response = \(String(describing: response))")

            // Print out reponse body
            let responseString = NSString(data: data!, encoding: String.Encoding.utf8.rawValue)
            // print("****** response data = \(responseString!)")

            do {
                let jsonResponseObject = try JSONSerialization.jsonObject(with: data!, options: []) as? NSDictionary

                // print(jsonResponseObject!)

                // Use Swiftly Json to Parse Json Value Into String
                let json = JSON(jsonResponseObject as Any)
                let fileName = json["url"].stringValue

                if param["sender"]! == "GetPet" {
                    let url = "lit-squad.com/files/images/pets/uploads/" + fileName
                    print(url)
                }

            } catch {
                print(error)
            }
        }

        task.resume()
    }

    // For Image Upload To Server Using PHP
    func createBodyWithParameters(parameters: [String: String]?, filePathKey: String?, imageDataKey: NSData, boundary: String) -> NSData {
        let body = NSMutableData()

        if parameters != nil {
            for (key, value) in parameters! {
                body.appendString(string: "--\(boundary)\r\n")
                body.appendString(string: "Content-Disposition: form-data; name=\"\(key)\"\r\n\r\n")
                body.appendString(string: "\(value)\r\n")
            }
        }

        let filename = "myfile.jpg"

        let mimetype = "image/jpg"

        body.appendString(string: "--\(boundary)\r\n")
        body.appendString(string: "Content-Disposition: form-data; name=\"\(filePathKey!)\"; filename=\"\(filename)\"\r\n")
        body.appendString(string: "Content-Type: \(mimetype)\r\n\r\n")
        body.append(imageDataKey as Data)
        body.appendString(string: "\r\n")

        body.appendString(string: "--\(boundary)--\r\n")

        return body
    }

    // For Image Upload To Server Using PHP
    func generateBoundaryString() -> String {
        return "Boundary-\(NSUUID().uuidString)"
    }
}

// For Image Upload To Server Using PHP
extension NSMutableData {
    func appendString(string: String) {
        let data = string.data(using: String.Encoding.utf8, allowLossyConversion: true)
        append(data!)
    }
}

// Image Picker
extension UIViewController: UIImagePickerControllerDelegate, UINavigationControllerDelegate {
    // Image Picker Controller Set Selected Image Into Image View
    public func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey: Any]) {
        let image = info[UIImagePickerController.InfoKey.originalImage]! as! UIImage

        // Dismiss The Image Picker And Set The Image
        picker.dismiss(animated: true, completion: {
            // Call The Image Cropper
            self.presentCropViewController(image: image)

        })
    }

    // Image Picker Cancel
    public func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {
        picker.dismiss(animated: true, completion: nil)
    }
}

// Image Cropper
extension UIViewController: CropViewControllerDelegate {
    // Image CropperView Function
    func presentCropViewController(image: UIImage) {
        let cropViewController = CropViewController(croppingStyle: .default, image: image)

        // Commenting This Because It Was Leading To Function Being Run Twice
        // cropViewController.delegate = self

        // CropperView Attributes
        cropViewController.title = "Crop Image"
        cropViewController.aspectRatioPreset = .presetSquare
        cropViewController.aspectRatioLockEnabled = true
        cropViewController.aspectRatioPickerButtonHidden = true

        present(cropViewController, animated: true, completion: nil)
    }

    // Image CropperView Finish Cropping
    public func cropViewController(_ cropViewController: CropViewController, didCropToImage image: UIImage, withRect cropRect: CGRect, angle: Int) {
        // bPetImage.setImage(image, for: UIControl.State.normal)

        // Call Function To Upload Image To Server
        myImageUploadRequest(image: image)

        cropViewController.dismiss(animated: true, completion: nil)
    }
}

基本上,这在swift文件(我已在其中注释过)中不起作用,但如果我在视图控制器本身中使用此扩展程序函数而没有扩展名,则它将起作用。

bPetImage.setImage(image, for: UIControl.State.normal)

我正在myImageUploadRequest(image: image)之前尝试以下操作

let viewController = GetPetViewController(nibName: nil, bundle: nil)
viewController.bPetImage.setImage(image, for: UIControl.State.normal)
navigationController?.pushViewController(viewController, animated: true)

但出现错误:Thread 1: Fatal error: Unexpectedly found nil while implicitly unwrapping an Optional value

1 个答案:

答案 0 :(得分:1)

因此,如果我正确理解了这一点,则可以使用另一个名为MyViewController的视图控制器,其中包含按钮bPetImage。并且此按钮现在应该获取图像。但是您所做的是将协议设置为无法访问按钮的超类UIViewController: CropViewControllerDelegate

针对您的情况的快速简便的解决方案可能是

(self as? MyViewController)?.bPetImage.setImage(image, for: UIControl.State.normal)

至少在您看来,selfMyViewController实例。通常,这不是一个很好的过程。我将创建一个特定的协议,而不是一个通用的协议。而是这样:

extension MyViewController: CropViewControllerDelegate {

在这种情况下,您可以直接调用它(您注释掉的代码)。

但是,如果您真的想要它,让UIViewController响应CropViewControllerDelegate,那么我只是建议您添加一个新协议。考虑这样的事情:

protocol SetCroppedImageDelegate {
    func setCroppedImage(_ image: UIImage)
}

现在您键入委托而不是具体的类了:

public func cropViewController(_ cropViewController: CropViewController, didCropToImage image: UIImage, withRect cropRect: CGRect, angle: Int) {
    (self as? SetCroppedImageDelegate)?.setCroppedImage(image)

    // Call Function To Upload Image To Server
    myImageUploadRequest(image: image)

    cropViewController.dismiss(animated: true, completion: nil)
}

现在您将扩展MyViewController

extension MyViewController : SetCroppedImageDelegate {
    func setCroppedImage(_ image: UIImage) {
        bPetImage.setImage(image, for: UIControl.State.normal)
    }
}