ios - Swift 3 使用 CKAsset 将图像发送到 CloudKit

标签 ios swift swift3 ios10 cloudkit

注意:这不是一个重复的问题,我看过其他解决方案,但没有一个在 Swift 3 中有效,但在 Swift 2 中有效。

我需要使用 UIImagePickerController 从照片库中获取图像,它工作正常,然后我需要做的是以某种方式将其保存到 CloudKit 中的公共(public)记录中,我对如何完成此操作持开放态度.如果可能,请明确我需要更改/添加的内容以及位置。

我提供了我的整个 View Controller 文件只是为了确定。

import UIKit
import CloudKit

var email: String = ""



class ViewController: UIViewController, UITextFieldDelegate, UIImagePickerControllerDelegate, UINavigationControllerDelegate {


    //MARK: Properties

    @IBOutlet weak var firstNameField: UITextField!
    @IBOutlet weak var lastNameField: UITextField!
    @IBOutlet weak var emailField: UITextField!
    @IBOutlet weak var passwordField: UITextField!
    @IBOutlet weak var confirmPasswordField: UITextField!
    @IBOutlet weak var notMatching: UILabel!
    @IBOutlet weak var emailLabel: UILabel!
    @IBOutlet weak var errorLabel: UILabel!

    @IBOutlet weak var photoImageView: UIImageView!



    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.

        self.firstNameField.autocorrectionType = .no
        self.lastNameField.autocorrectionType = .no
        self.emailField.autocorrectionType = .no
        self.passwordField.autocorrectionType = .no
        self.confirmPasswordField.autocorrectionType = .no
        self.notMatching.isHidden = true

        firstNameField.delegate = self
        lastNameField.delegate = self
        emailField.delegate = self
        passwordField.delegate = self
        confirmPasswordField.delegate = self


    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

    //MARK: UIImagePickerControllerDelegate

    func imagePickerControllerDidCancel(_ picker: UIImagePickerController) {

        // Dismiss the picker if the user canceled.
        dismiss(animated: true, completion: nil)

    }

    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : Any]) {

        // The info dictionary may contain multiple representations of the image. You want to use the original.
        guard let selectedImage = info[UIImagePickerControllerOriginalImage] as? UIImage else {
            fatalError("Expected a dictionary containing an image, but was provided the following: \(info)")
        }

        // Set photoImageView to display the selected image.
        photoImageView.image = selectedImage



        // Dismiss the picker.
        dismiss(animated: true, completion: nil)


    }


    //MARK: Actions

    @IBAction func selectImageFromPhotoLibrary(_ sender: UITapGestureRecognizer) {

        //Hide keyboards
        firstNameField.resignFirstResponder()
        lastNameField.resignFirstResponder()
        emailField.resignFirstResponder()
        passwordField.resignFirstResponder()
        confirmPasswordField.resignFirstResponder()

        let imagePickerController = UIImagePickerController()

        imagePickerController.sourceType = .photoLibrary


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

    }



    @IBAction func signUpPressed(_ sender: UIButton) {

        let container = CKContainer.default()
        let pubDB = container.publicCloudDatabase
        //let privDB = container.privateCloudDatabase

        //Check if users exist
        let query = CKQuery(recordType: "MyUsers", predicate: NSPredicate(format: "TRUEPREDICATE", argumentArray: nil))
        pubDB.perform(query, inZoneWith: nil, completionHandler: { (records, error) in

            //error code 11 is no objects found
            if error == nil || error?._code == 11 {

                var emailExists = false

                for record in records! {

                    if record.object(forKey: "email") as? String == self.emailField.text {
                        //other user with the same username exists - don't allow user to create account
                        emailExists = true

                    }

                }

                if emailExists == true {


                    self.emailLabel.text = "\(self.emailField.text!) is taken. Please choose another one."

                } else {

                    if self.firstNameField.text != nil && self.lastNameField.text != nil && self.passwordField.text == self.confirmPasswordField.text {

                        //user can sign up


                        let record = CKRecord(recordType: "MyUsers")
                        record.setObject(self.emailField.text! as CKRecordValue?, forKey: "email")
                        record.setObject(self.passwordField.text! as CKRecordValue?, forKey: "password")
                        record.setObject(self.firstNameField.text! as CKRecordValue?, forKey: "firstName")
                        record.setObject(self.lastNameField.text! as CKRecordValue?, forKey: "lastName")



                        print("all good")

                        pubDB.save(record, completionHandler: { (record, error) in

                            if error == nil {

                                OperationQueue.main.addOperation {

                                    UserDefaults.standard.set(self.emailField.text!, forKey: "Email")
                                    email = self.emailField.text!
                                    //self.performSegue(withIdentifier: "Games", sender: self)

                                }

                            } else {

                                print(error)

                            }

                        })


                    } else {



                    }


                }



            } else {

                print(error)

            }

        })

    }



    // MARK: UITextFieldDelegate

    func textFieldShouldReturn(_ textField: UITextField) -> Bool {
        // Hide the keyboard.
        textField.resignFirstResponder()
        return true
    }



}

谢谢!

最佳答案

这是使用 CloudKit 将图像保存为 CKAsset 的简单方法。请确保在设置记录时更改记录的名称和 Assets 的字段名称。

let documentsDirectoryPath:NSString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
var imageURL: URL!
let tempImageName = "Image2.jpg"


func saveImage(_ image: UIImage?) {

    // Create a CKRecord
    let newRecord:CKRecord = CKRecord(recordType: "<INSERT_RECORD_NAME")

    if let image = image {

        let imageData:Data = UIImageJPEGRepresentation(image, 1.0)!
        let path:String = self.documentsDirectoryPath.appendingPathComponent(self.tempImageName)
        try? UIImageJPEGRepresentation(image, 1.0)!.write(to: URL(fileURLWithPath: path), options: [.atomic])
        self.imageURL = URL(fileURLWithPath: path)
        try? imageData.write(to: self.imageURL, options: [.atomic])

        let File:CKAsset?  = CKAsset(fileURL: URL(fileURLWithPath: path))
        newRecord.setObject(File, forKey: "<INSERT_RECORD_ASSET_FIELD_NAME")
    }

    if let database = self.publicDatabase {

        database.save(newRecord, completionHandler: { (record:CKRecord?, error:Error?) in

            // Check if there was an error
            if error != nil {
                NSLog((error?.localizedDescription)!)
            }
            else if let record = record {

                // Do whatever you want with the record, but image record was saved, asset should be saved.

            }


        })


    }


}

如果你不能做 JPEG 格式,并且需要保存为 .png 你可以用这个替换 UIImageJPEGRepresentation 部分:

let imageData:Data = UIImagePNGRepresentation(image)!
try? UIImagePNGRepresentation(image)!.write(to: URL(fileURLWithPath: path), options: [.atomic])

并使 tempImageName 类似于 let tempImageName = "Image2.png"

希望对你有帮助

关于ios - Swift 3 使用 CKAsset 将图像发送到 CloudKit,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41643683/

相关文章:

ios - 使用 RXSwift 的警报消息的 UIViewController 扩展

ios - 在第一个 View Controller 中添加 'addObserver' (NSNotificationCenter),在第二个 View Controller 中处理

ios - 在 iOS 中归档发布版本之前,有什么方法可以自动运行我所有的单元测试

ios - 如何迅速删除套件的所有默认值/NSUserDefaults值?

ios - 将 [FIRApp configure] 添加到您的应用程序初始化错误中

ios - 关闭 viewController 总是触发 viewDidLoad 并且从不触发 viewWillAppear

ios - CloudKit 错误 "Bad Container"(5/1014); "Couldn' t 从服务器获取容器配置 "iCloud.com.abc.def"">

ios - 从 tableView 中删除一行的正确方法是什么?

ios - 如何在objective-c项目中使用swift类别?

swift - 如何在 Swift 中共享图像