Building SQLite Database with Photos - ios

I am aiming to display images collected by the user from a DetailViewController, in a UICollectionView controller. I want to use a SQLite Database, but am unsure how to start it, seeing as I already have most of my app built and established. Below see my DetailViewController (where the images are collection and displayed), ImageStore.swift (Where the images are currently being stored), and the UICollectionView controller.
ImageStore.swift:
class ImageStore: NSObject {
let cache = NSCache()
func setImage(image: UIImage, forKey key: String) {
cache.setObject(image, forKey: key)
let imageURL = imageURLForKey(key)
if let data = UIImageJPEGRepresentation(image, 0.5) {
data.writeToURL(imageURL, atomically: true)
}
}
func imageForKey(key: String) -> UIImage? {
if let existingImage = cache.objectForKey(key) as? UIImage {
return existingImage
}
let imageURL = imageURLForKey(key)
guard let imageFromDisk = UIImage(contentsOfFile: imageURL.path!) else {
return nil
}
cache.setObject(imageFromDisk, forKey: key)
return imageFromDisk
}
func deleteImageForKey(key: String) {
cache.removeObjectForKey(key)
let imageURL = imageURLForKey(key)
do {
try NSFileManager.defaultManager().removeItemAtURL(imageURL)
}
catch let deleteError {
print("Error removing the image from disk: \(deleteError)")
}
}
func imageURLForKey(key: String) -> NSURL {
let documentsDirectories = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let documentDirectory = documentsDirectories.first!
return documentDirectory.URLByAppendingPathComponent(key)
}
DetailViewController:
var imageStore: ImageStore!
#IBAction func takePicture(sender: UIBarButtonItem) {
let imagePicker = UIImagePickerController()
if UIImagePickerController.isSourceTypeAvailable(.Camera) {
imagePicker.sourceType = .Camera
} else {
imagePicker.sourceType = .PhotoLibrary
}
imagePicker.delegate = self
presentViewController(imagePicker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: AnyObject]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
imageStore.setImage(image, forKey: item.itemKey)
imageView.image = image
dismissViewControllerAnimated(true, completion: nil)
}
UICollectionView:
class PhotosViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 100, height: 100)
let myCollectionView:UICollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
myCollectionView.dataSource = self
myCollectionView.delegate = self
myCollectionView.registerClass(RDCellCollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
myCollectionView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(myCollectionView)
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
var images: [UIImage] = [
]
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let myCell = collectionView.dequeueReusableCellWithReuseIdentifier("MyCell", forIndexPath: indexPath) as! RDCellCollectionViewCell
myCell.imageView.image = images[indexPath.item]
return myCell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
print("User tapped on item \(indexPath.row)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}

Related

Accessing images in DocumentDirectory iOS and UICollectionView

In my app, the user selects an image from camera roll, and it is saved in a document directory. The image is then displayed on the ViewController where they selected the image. I want the image to be appended to a UICollectionView. How can I access the image/append the image from the documentDirectory? Please see my code below. Let me know if you need other pieces of my project.
DetailViewController(Where I initially display the photo):
class DetailViewController: UIViewController, UITextFieldDelegate, UINavigationControllerDelegate, UIImagePickerControllerDelegate {
...
var imageStore: ImageStore!
#IBAction func takePicture(sender: UIBarButtonItem) {
let imagePicker = UIImagePickerController()
if UIImagePickerController.isSourceTypeAvailable(.Camera) {
imagePicker.sourceType = .Camera
} else {
imagePicker.sourceType = .PhotoLibrary
}
imagePicker.delegate = self
presentViewController(imagePicker, animated: true, completion: nil)
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String: AnyObject]) {
let image = info[UIImagePickerControllerOriginalImage] as! UIImage
imageStore.setImage(image, forKey: item.itemKey)
imageView.image = image
dismissViewControllerAnimated(true, completion: nil)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let key = item.itemKey
if let imageToDisplay = imageStore.imageForKey(key) {
imageView.image = imageToDisplay
}
}
ImageStore(How I initially store the photo):
import UIKit
class ImageStore: NSObject {
let cache = NSCache()
func setImage(image: UIImage, forKey key: String) {
cache.setObject(image, forKey: key)
let imageURL = imageURLForKey(key)
if let data = UIImageJPEGRepresentation(image, 0.5) {
data.writeToURL(imageURL, atomically: true)
}
}
func imageForKey(key: String) -> UIImage? {
if let existingImage = cache.objectForKey(key) as? UIImage {
return existingImage
}
let imageURL = imageURLForKey(key)
guard let imageFromDisk = UIImage(contentsOfFile: imageURL.path!) else {
return nil
}
cache.setObject(imageFromDisk, forKey: key)
return imageFromDisk
}
func deleteImageForKey(key: String) {
cache.removeObjectForKey(key)
let imageURL = imageURLForKey(key)
do {
try NSFileManager.defaultManager().removeItemAtURL(imageURL)
}
catch let deleteError {
print("Error removing the image from disk: \(deleteError)")
}
}
func imageURLForKey(key: String) -> NSURL {
let documentsDirectories =
NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let documentDirectory = documentsDirectories.first!
return documentDirectory.URLByAppendingPathComponent(key)
}
}
UICollectionView:
import UIKit
class PhotosViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 300, height: 490)
collectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
collectionView.dataSource = self
collectionView.delegate = self
collectionView!.registerClass(FoodCell.self, forCellWithReuseIdentifier: "Cell")
collectionView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(collectionView)
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
var images: [UIImage] = [
]
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! FoodCell
cell.textLabel.text = ""
cell.imageView.image = images[indexPath.row]
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
print("User tapped on item \(indexPath.row)")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
You can try to save and get your image by this way:
//Save image
let img = UIImage() // Image from your picker
let data = UIImagePNGRepresentation(img)!
do {
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
try data.writeToFile("\(documentsPath)myImage", options: [])
} catch {
print("Error")
}
// Get image
do {
let documentsPath = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as String
let readData = try NSData(contentsOfFile: "\(documentsPath)myImage", options: [])
let retreivedImage = UIImage(data: readData)
}
catch {
print("Error")
}
Same way as https://stackoverflow.com/a/35685943/2894160

Creating UICollectionView programmatically

I am learning how to create a UICollectionView programmatically. I want to create a grid of pictures collected from the user in another part of the app.
Will this sample code help me accomplish this? Also, how do I configure the data to emit the image I want? My source code is below.
UICollectionView:
class PhotosViewController: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
override func viewDidLoad() {
super.viewDidLoad()
let imageStore = ImageStore()
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.sectionInset = UIEdgeInsets(top: 20, left: 10, bottom: 10, right: 10)
layout.itemSize = CGSize(width: 100, height: 100)
let myCollectionView:UICollectionView = UICollectionView(frame: self.view.frame, collectionViewLayout: layout)
myCollectionView.dataSource = self
myCollectionView.delegate = self
myCollectionView.registerClass(RDCellCollectionViewCell.self, forCellWithReuseIdentifier: "MyCell")
myCollectionView.backgroundColor = UIColor.whiteColor()
self.view.addSubview(myCollectionView)
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return images.count
}
var images: [UIImage] = [
]
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
let myCell = collectionView.dequeueReusableCellWithReuseIdentifier("MyCell", forIndexPath: indexPath) as! RDCellCollectionViewCell
myCell.imageView.image = images[indexPath.item]
myCell.backgroundColor = UIColor.grayColor()
return myCell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
print("User tapped on item \(indexPath.row)")
}
}
ImageStore.swift:
class ImageStore: NSObject {
let cache = NSCache()
func setImage(image: UIImage, forKey key: String) {
cache.setObject(image, forKey: key)
let imageURL = imageURLForKey(key)
if let data = UIImageJPEGRepresentation(image, 0.5) {
data.writeToURL(imageURL, atomically: true)
}
}
func imageForKey(key: String) -> UIImage? {
if let existingImage = cache.objectForKey(key) as? UIImage {
return existingImage
}
let imageURL = imageURLForKey(key)
guard let imageFromDisk = UIImage(contentsOfFile: imageURL.path!) else {
return nil
}
cache.setObject(imageFromDisk, forKey: key)
return imageFromDisk
}
func deleteImageForKey(key: String) {
cache.removeObjectForKey(key)
let imageURL = imageURLForKey(key)
do {
try NSFileManager.defaultManager().removeItemAtURL(imageURL)
}
catch let deleteError {
print("Error removing the image from disk: \(deleteError)")
}
}
func imageURLForKey(key: String) -> NSURL {
let documentsDirectories =
NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask)
let documentDirectory = documentsDirectories.first!
return documentDirectory.URLByAppendingPathComponent(key)
}
}
You're on the right track. You'll need to create a subclass of UICollectionViewCell that contains a UIImageView; this will let you plug the correct UIImage into it in cellForItemAtIndexPath.
This describes how to hook up your custom cell:
Create UICollectionViewCell programmatically without nib or storyboard
As for getting the correct image, you'll need to map the index path to your image store somehow, so that an item number corresponds to the correct image key.
If the task is to add an image, you should use something like this in cellForItemAtIndexPath:
let myCell = collectionView.dequeueReusableCellWithReuseIdentifier("MyCell", forIndexPath: indexPath)
myCell.backgroundColor = UIColor.blueColor()
let imageView = UIImageView(frame: cell.contentView.frame)
cell.contentView.addSubview(imageView)
imageView.image = //Here you should get right UIImage like ImageStore().imageForKey("YOUR_KEY")
return myCell
Or you can use custom UICollectionViewCell subclass as Joshua Kaden wrote.

Photos framework.How to get date and location fromt the selected image

I have a collectionview which loads from the library. The selected image is displayed in another viewcontroller. I want to fetch the exif data from the image(location and date). How should I modify the code to do this?
the code for the page listing images is shown below:
import UIKit
import Photos
import MobileCoreServices
private let reuseIdentifier = "PhotoCell"
class AddPhotoViewController: UIViewController , UIImagePickerControllerDelegate ,UINavigationControllerDelegate ,UICollectionViewDataSource ,UICollectionViewDelegate{
#IBOutlet weak var photoAlbum: UICollectionView!
var TakenImage : UIImage?
var newMedia: Bool?
var selectedImage : UIImage!
var pickedImage : UIImage!
var assetCollection: PHAssetCollection!
var photosAsset: PHFetchResult!
var assetThumbnailSize: CGSize!
let imagePicker: UIImagePickerController! = UIImagePickerController()
var cameraon : Bool = false
var index : [NSIndexPath]!
var note : String!
var tags = ""
var noteAlreadyEntered = false
override func viewDidLoad()
{
super.viewDidLoad()
self.navigationController?.navigationBar.barTintColor = UIColor.grayColor()
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .SmartAlbumUserLibrary, options: nil)
var i = 0
repeat
{
if (collection.count > 0)
{
if let first_Obj:AnyObject = collection.objectAtIndex(i)
{
self.assetCollection = first_Obj as! PHAssetCollection
}
i += 1
}
}while( i < collection.count)
// Do any additional setup after loading the view.
}
func takePhoto(sender : UIButton)
{
if (UIImagePickerController.isSourceTypeAvailable(.Camera))
{
if UIImagePickerController.availableCaptureModesForCameraDevice(.Rear) != nil {
imagePicker.allowsEditing = false
imagePicker.sourceType = .Camera
imagePicker.cameraCaptureMode = .Photo
presentViewController(imagePicker, animated: true, completion: {})
} else {
print("Rear camera doesn't exist Application cannot access the camera.")
}
} else {
print("Camera inaccessable Application cannot access the camera.")
}
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject])
{
print("Got an image")
if let pickedImage:UIImage = (info[UIImagePickerControllerOriginalImage]) as? UIImage {
let selectorToCall = Selector("imageWasSavedSuccessfully:didFinishSavingWithError:context:")
UIImageWriteToSavedPhotosAlbum(pickedImage, self, selectorToCall, nil)
TakenImage = pickedImage
}
imagePicker.dismissViewControllerAnimated(true, completion: {
// Anything you want to happen when the user saves an image
})
}
func imagePickerControllerDidCancel(picker: UIImagePickerController)
{
print("User canceled image")
dismissViewControllerAnimated(true, completion: {
// Anything you want to happen when the user selects cancel
})
}
override func viewWillAppear(animated: Bool)
{
if let layout = self.photoAlbum!.collectionViewLayout as? UICollectionViewFlowLayout{
let cellSize = layout.itemSize
self.assetThumbnailSize = CGSizeMake(cellSize.width, cellSize.height)
}
//fetch the photos from collection
self.photosAsset = PHAsset.fetchAssetsInAssetCollection(self.assetCollection, options: nil)
self.photoAlbum!.reloadData()
}
// MARK: UICollectionViewDelegate
/*
// Uncomment this method to specify if the specified item should be selected
override func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
*/
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if (segue.identifier == "saveSelected")
{
let cell = sender as! PhotoAlbumCollectionViewCell
let indexPath = photoAlbum.indexPathForCell(cell)
let destVC = segue.destinationViewController as! NoteDetailViewController
destVC.asset = self.photosAsset[indexPath!.item] as! PHAsset
destVC.flag = true
if(noteAlreadyEntered == true)
{
destVC.content = note
if (self.tags != "")
{
destVC.tagsTextField.text = self.tags
}
}
}
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath)
{
if (indexPath.row == 0)
{
let controller = self.storyboard!.instantiateViewControllerWithIdentifier("NoteDetailViewController") as! NoteDetailViewController
controller.takinPhoto = true
if(noteAlreadyEntered == true)
{
controller.content = note
controller.imageView.image = TakenImage
controller.tagsTextField.text = self.tags
}
else
{
controller.imageView2.image = TakenImage
controller.tagsTextField.text = self.tags
}
self.navigationController!.pushViewController(controller, animated: true)
}
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
{
// #warning Incomplete implementation, return the number of sections
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
// #warning Incomplete implementation, return the number of items
var count: Int = 0
if(self.photosAsset != nil){
count = self.photosAsset.count
}
print("\(self.photosAsset.count)")
return count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell: PhotoAlbumCollectionViewCell = photoAlbum.dequeueReusableCellWithReuseIdentifier("PhotoCell", forIndexPath: indexPath) as! PhotoAlbumCollectionViewCell
if (indexPath.item == 0)
{
let btn = UIButton(frame: cell.contentView.bounds) //Set your frame that you want
// btn.setBackgroundImage(UIImage(named: "Compact Camera Filled-50.png"), forState: .Normal)
btn.setImage(UIImage(named: "Compact Camera Filled-50.png"), forState: .Normal)
btn.addTarget(self, action: "takePhoto:", forControlEvents: UIControlEvents.TouchUpInside)
cell.contentView.addSubview(btn)
}
else
{
let asset: PHAsset = self.photosAsset[indexPath.item] as! PHAsset
PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: self.assetThumbnailSize, contentMode: .AspectFill, options: nil, resultHandler: {(result, info)in
if let image = result {
cell.setThumbnailImage(image)
}
})
}
return cell
}
func collectionView(collectinView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 4
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 1
}
func collectionView(collectionView: UICollectionView, shouldShowMenuForItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
func collectionView(collectionView: UICollectionView, canPerformAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) -> Bool {
return false
}
func collectionView(collectionView: UICollectionView, performAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) {
self.dismissViewControllerAnimated(false, completion: nil)
}
}
A photo is a PHAsset. PHAsset gives you properties representing its metadata.
If you want the raw EXIF metadata you'll have to pass through something like CIImage.

UICollectionview which loads photos from library.How to pass Image to another viewcontroller

I have a collectionview which loads images from photo library using photos framework.I have added a segue named saveSelected for the purpose of passing the selected image to another viewController NoteDetailViewController.How can I pass the same
My AddPhotoViewController is given below
import UIKit
import Photos
private let reuseIdentifier = "PhotoCell"
class AddPhotoViewController: UIViewController , UIImagePickerControllerDelegate ,UINavigationControllerDelegate ,UICollectionViewDataSource ,UICollectionViewDelegate
{
#IBOutlet weak var photoAlbum: UICollectionView!
var TakenImage : UIImageView!
var assetCollection: PHAssetCollection!
var photosAsset: PHFetchResult!
var assetThumbnailSize: CGSize!
let imagePicker: UIImagePickerController! = UIImagePickerController()
var cameraon : Bool = false
override func viewDidLoad()
{
super.viewDidLoad()
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .SmartAlbumUserLibrary, options: nil)
var i = 0
repeat
{
if let first_Obj:AnyObject = collection.objectAtIndex(i)
{
self.assetCollection = first_Obj as! PHAssetCollection
}
i++
}while( i < collection.count)
// Do any additional setup after loading the view.
}
#IBAction func takePhoto(sender: AnyObject) {
if (UIImagePickerController.isSourceTypeAvailable(.Camera)) {
if UIImagePickerController.availableCaptureModesForCameraDevice(.Rear) != nil {
imagePicker.allowsEditing = false
imagePicker.sourceType = .Camera
imagePicker.cameraCaptureMode = .Photo
presentViewController(imagePicker, animated: true, completion: {})
cameraon = true
} else {
print("Rear camera doesn't exist")
}
} else {
print("Camera inaccessable")
}
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
TakenImage.image = image
if (cameraon)
{
let imageData = UIImageJPEGRepresentation(TakenImage.image!, 0.6)
let compressedJPGImage = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(compressedJPGImage!, nil, nil, nil)
}
self.dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
print("User canceled image")
dismissViewControllerAnimated(true, completion: {
// Anything you want to happen when the user selects cancel
})
}
override func viewWillAppear(animated: Bool)
{
if let layout = self.photoAlbum!.collectionViewLayout as? UICollectionViewFlowLayout{
let cellSize = layout.itemSize
self.assetThumbnailSize = CGSizeMake(cellSize.width, cellSize.height)
}
//fetch the photos from collection
self.photosAsset = PHAsset.fetchAssetsInAssetCollection(self.assetCollection, options: nil)
self.photoAlbum!.reloadData()
}
// MARK: UICollectionViewDelegate
/*
// Uncomment this method to specify if the specified item should be selected
override func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
*/
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if (segue.identifier == "savePhoto")
{
if let controller : NoteDetailViewController = segue.destinationViewController as? NoteDetailViewController
{
controller.imageView.image = TakenImage.image
}
}
/* if (segue.identifier == "saveSelected")
{
if let controller2 : NoteDetailViewController = segue.destinationViewController as? NoteDetailViewController
{
if let cell = photoAlbum.cel as? PhotoAlbumCollectionViewCell
{
}
}
}*/
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
{
// #warning Incomplete implementation, return the number of sections
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
// #warning Incomplete implementation, return the number of items
var count: Int = 0
if(self.photosAsset != nil){
count = self.photosAsset.count
}
print("\(self.photosAsset.count)")
return count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell: PhotoAlbumCollectionViewCell = photoAlbum.dequeueReusableCellWithReuseIdentifier("PhotoCell", forIndexPath: indexPath) as! PhotoAlbumCollectionViewCell
//Modify the cell
let asset: PHAsset = self.photosAsset[indexPath.item] as! PHAsset
PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: self.assetThumbnailSize, contentMode: .AspectFill, options: nil, resultHandler: {(result, info)in
if let image = result {
cell.setThumbnailImage(image)
}
})
return cell
}
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
}
func collectionView(collectinView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 4
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 1
}
func collectionView(collectionView: UICollectionView, shouldShowMenuForItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
func collectionView(collectionView: UICollectionView, canPerformAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) -> Bool {
return false
}
func collectionView(collectionView: UICollectionView, performAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) {
self.dismissViewControllerAnimated(false, completion: nil)
}
}
How should I modify the didSelectItemAtIndexPath and prepareForSegue to achieve this?
You have set segue with CollectionViewCell so there is no need to write any thing in your didSelectItemAtIndexPath method, Change your code like this in prepareForSegue method
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "saveSelected")
{
let cell = sender as! PhotoAlbumCollectionViewCell
let indexPath = tableView.indexPathForCell(cell)
let destVC = segue.destinationViewController as! NoteDetailViewController
destVC.asset = self.photosAsset[indexPath.item] as! PHAsset
}
}
Now create one global object with name asset in NoteDetailViewController like this
var asset: PHAsset!
Now add like below code in your viewDidLoad of NoteDetailViewController
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: self.assetThumbnailSize, contentMode: .AspectFill, options: nil, resultHandler: {(result, info)in
if let image = result {
self.imageView.image = image
}
})
}
Hope this will help you.
You can't set any imageviews or outlets before the controller is loaded, so you've to modify your segue code and the other controller to have an image that will be sent when segued.
if (segue.identifier == "savePhoto")
{
if let controller : NoteDetailViewController = segue.destinationViewController as? NoteDetailViewController
{
controller.image = TakenImage.image
}
}
then modify the segued class:
class NoteDetailViewController: UITableViewController {
var image: UIImage!
}

Resizing an image when the cell in a UICollectionView is selected

I have a UICollectionview with an imageview in the cell.The UICollectionview loads data from photolibrary. When the user selects an image it needs to be passed to another viewcontroller (NoteDetailViewController).This is working. But the image clarity is lost when passed to the other viewcontroller. Can anyone help me, how to modify the prepareForSegue method?
the code for the same is given below
import UIKit
import Photos
private let reuseIdentifier = "PhotoCell"
class AddPhotoViewController: UIViewController , UIImagePickerControllerDelegate ,UINavigationControllerDelegate ,UICollectionViewDataSource ,UICollectionViewDelegate
{
#IBOutlet weak var photoAlbum: UICollectionView!
var TakenImage : UIImageView!
var assetCollection: PHAssetCollection!
var photosAsset: PHFetchResult!
var assetThumbnailSize: CGSize!
let imagePicker: UIImagePickerController! = UIImagePickerController()
var cameraon : Bool = false
override func viewDidLoad()
{
super.viewDidLoad()
let collection:PHFetchResult = PHAssetCollection.fetchAssetCollectionsWithType(.SmartAlbum, subtype: .SmartAlbumUserLibrary, options: nil)
var i = 0
repeat
{
if let first_Obj:AnyObject = collection.objectAtIndex(i)
{
self.assetCollection = first_Obj as! PHAssetCollection
}
i++
}while( i < collection.count)
// Do any additional setup after loading the view.
}
#IBAction func takePhoto(sender: AnyObject) {
if (UIImagePickerController.isSourceTypeAvailable(.Camera)) {
if UIImagePickerController.availableCaptureModesForCameraDevice(.Rear) != nil {
imagePicker.allowsEditing = false
imagePicker.sourceType = .Camera
imagePicker.cameraCaptureMode = .Photo
presentViewController(imagePicker, animated: true, completion: {})
cameraon = true
} else {
print("Rear camera doesn't exist")
}
} else {
print("Camera inaccessable")
}
}
func imagePickerController(picker: UIImagePickerController, didFinishPickingImage image: UIImage!, editingInfo: [NSObject : AnyObject]!) {
TakenImage.image = image
if (cameraon)
{
let imageData = UIImageJPEGRepresentation(TakenImage.image!, 0.6)
let compressedJPGImage = UIImage(data: imageData!)
UIImageWriteToSavedPhotosAlbum(compressedJPGImage!, nil, nil, nil)
}
self.dismissViewControllerAnimated(true, completion: nil)
}
func imagePickerControllerDidCancel(picker: UIImagePickerController) {
print("User canceled image")
dismissViewControllerAnimated(true, completion: {
// Anything you want to happen when the user selects cancel
})
}
override func viewWillAppear(animated: Bool)
{
if let layout = self.photoAlbum!.collectionViewLayout as? UICollectionViewFlowLayout{
let cellSize = layout.itemSize
self.assetThumbnailSize = CGSizeMake(cellSize.width, cellSize.height)
}
//fetch the photos from collection
self.photosAsset = PHAsset.fetchAssetsInAssetCollection(self.assetCollection, options: nil)
self.photoAlbum!.reloadData()
}
// MARK: UICollectionViewDelegate
/*
// Uncomment this method to specify if the specified item should be selected
override func collectionView(collectionView: UICollectionView, shouldSelectItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
*/
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?)
{
if (segue.identifier == "savePhoto")
{
if let controller : NoteDetailViewController = segue.destinationViewController as? NoteDetailViewController
{
controller.imageView.image = TakenImage.image
}
}
if (segue.identifier == "saveSelected")
{
if let controller:NoteDetailViewController = segue.destinationViewController as? NoteDetailViewController
{
if let cell = sender as? PhotoAlbumCollectionViewCell
{
let imageToPass = cell.imageView.image
controller.someImage = imageToPass
}
}
}
}
func numberOfSectionsInCollectionView(collectionView: UICollectionView) -> Int
{
// #warning Incomplete implementation, return the number of sections
return 1
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
// #warning Incomplete implementation, return the number of items
var count: Int = 0
if(self.photosAsset != nil){
count = self.photosAsset.count
}
print("\(self.photosAsset.count)")
return count
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell
{
let cell: PhotoAlbumCollectionViewCell = photoAlbum.dequeueReusableCellWithReuseIdentifier("PhotoCell", forIndexPath: indexPath) as! PhotoAlbumCollectionViewCell
//Modify the cell
let asset: PHAsset = self.photosAsset[indexPath.item] as! PHAsset
PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: self.assetThumbnailSize, contentMode: .AspectFill, options: nil, resultHandler: {(result, info)in
if let image = result {
cell.setThumbnailImage(image)
}
})
return cell
}
func collectionView(collectinView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAtIndex section: Int) -> CGFloat {
return 4
}
func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAtIndex section: Int) -> CGFloat {
return 1
}
func collectionView(collectionView: UICollectionView, shouldShowMenuForItemAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
func collectionView(collectionView: UICollectionView, canPerformAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) -> Bool {
return false
}
func collectionView(collectionView: UICollectionView, performAction action: Selector, forItemAtIndexPath indexPath: NSIndexPath, withSender sender: AnyObject?) {
self.dismissViewControllerAnimated(false, completion: nil)
}
}
First you request the targetSize to be the one of thumbnail in cellForRowAtIndexPath.
Now inside prepareForSegue you need to ask the PHImageManager for the asset again but now using a bigger TargetSize, one that fits your needs
You can ask the collectionView for the indexPathsForSelectedItems() which you can use to know which asset the user selected
if (segue.identifier == "saveSelected")
{
if let controller:NoteDetailViewController = segue.destinationViewController as? NoteDetailViewController
{
if let cell = sender as? PhotoAlbumCollectionViewCell
{
let asset: PHAsset = self.photosAsset[indexPath.item] as! PHAsset
PHImageManager.defaultManager().requestImageForAsset(asset, targetSize: controller.view.size, contentMode: .AspectFill, options: nil, resultHandler: {(result, info)in
if let image = result {
cell.setThumbnailImage(image)
}
})
controller.someImage = imageToPass
}
}
}

Resources