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

时间:2017-01-13 21:25:19

标签: ios swift swift3 ios10 cloudkit

N.B:这不是一个重复的问题,我看过其他解决方案,但没有一个在Swift 3中工作,但是他们在Swift 2中工作。

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

我提供了我的整个视图控制器文件以确定。

导入UIKit 导入CloudKit

var email:String =“”

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

}

谢谢!

2 个答案:

答案 0 :(得分:6)

以下是使用CKAsset将图片另存为CloudKit的简单方法。请确保更改记录的名称,以及设置记录时资产的字段名称。

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"

希望这有帮助

答案 1 :(得分:0)

Swift 5版本,但抽象为一个函数,可以在其中传递UI Image对象并返回要使用的URL。在将图像保存在CoreData中并想稍后再上传到CloudKit的地方很有用。

func getImageURL(for image: UIImage?) -> URL {
    let documentsDirectoryPath:NSString = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString
    let tempImageName = "tempImage.jpg"
    var imageURL: URL?

    if let image = image {

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

然后是我的用法:

  let imageURL = getImageURL(for: UIImage(data: itemToPublish!.Photo!)!)
  let imageAsset = CKAsset(fileURL: imageURL)
            itemBeingUpdated["photo"] = imageAsset  

  CKContainer.default().publicCloudDatabase.save(challengeRecord) { ...