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

标签 ios swift

我在扩展中使用 cropViewController 来裁剪图像。结果出现在一个 swift 文件中(不是 View Controller )。但是现在需要在另一个 View Controller 中设置图像。

正在使用 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)
    }
}

我的第二个文件(不是 View Controller )

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 文件中不起作用(我在其中对其进行了评论),但如果我在 View Controller 本身中使用没有扩展名的裁剪器功能,它将起作用。

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

最佳答案

因此,如果我的理解正确,您还有其他一些名为 MyViewController 的 View Controller ,它包含按钮 bPetImage。这个按钮现在应该得到图像。但是您所做的是将协议(protocol)设置为父类(super class) UIViewController: CropViewControllerDelegate,它无权访问按钮。

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

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

至少我希望在您的情况下 selfMyViewController 实例。一般来说,这不是一个很好的程序。我会创建一个特定的协议(protocol),而不是一个通用的协议(protocol)。所以宁愿有:

extension MyViewController: CropViewControllerDelegate {

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

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

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

现在您对委托(delegate)而不是具体类进行类型转换:

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)
    }
}

关于ios - 将图像从 Swift 文件(不是 ViewController)传递到 ViewController,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56930994/

相关文章:

ios - 如何将 Touch ID 与登录凭据相关联?

swift - 具有动态高度单元格和填充页脚 View 的 UITableview

ios - 我如何在我自己的 iOS 项目中使用 pjsip?

iOS :Can I use custom URL scheme to communicate a flag between three applications should be always in background

带有 AVCaptureVideoDataOutput 的 iOS 应用程序在 App Store 版本中崩溃

swift - 移动时将球体附加到设备屏幕的中心

ios - 如何在 iOS 编程中使用 Swift 创建实体文件?

Swift 2.0 复制 OBJC_ASSOCIATION_RETAIN

ios - 某些文件未显示在 Xcode 项目导航器中

ios - 在 NavigationView 前面放置可交互的 View 隐藏导航栏