How to pass UI image from one view controller to another? - ios

I need to pass a image from one view controller to another I had user NSuserdefault to declare the image variable as global but it shows this error app due to uncaught exception 'NSInvalidArgumentException', reason: 'Attempt to insert non-property list object
func imagePickerController(picker: UIImagePickerController!, didFinishPickingImage image: UIImage!, editingInfo: NSDictionary!) {
self.dismissViewControllerAnimated(true, completion: { () -> Void in
})
imageview.image = image
NSUserDefaults.standardUserDefaults().setObject(image, forKey:"image")
NSUserDefaults.standardUserDefaults().synchronize()
}

You can't save image directly into the UserDefaults, You can compress image to png/jpeg data,and you can save the data into the userDefault. using method
NSData *UIImagePNGRepresentation(UIImage *image);
and
if imageData {
NSUserDefaults.standardUserDefaults().setObject(imageData, forKey:"image")
NSUserDefaults.standardUserDefaults().synchronize()
}
when you read the userDefaults, you can read data firstly, then convert data to image using method
UIImage-imageWithData: or swift style UIImage(data:)
generally, we don't do like above, we save image to file, and save the file's path into the userDefault

What do you means? Pass a UIImage's variables to another viewController? The information you provide is too little.
Maybe you want to look this link Using Delegation to Communicate With Other View Controllers.

Simply create a property of NSString *imageName and setting it before pushing/presenting a viewcontroller ,and in your other viewcontroller you could read this property to create a UIImage.

To store the image with NSUSerdefaults:
var testimage = UIImage(named: "testimage.png");
NSUserDefaults.standardUserDefaults().setObject(UIImagePNGRepresentation(testimage), forKey:"image")
}
To retrieve it in another class:
var imagedata: NSData = NSUserDefaults.standardUserDefaults().dataForKey("image")!
imageview.image = UIImage (data: imagedata)

Related

UIImagePickerController - how to save image to core data? (Swift)

I want to save the image that I have picked from the ImagePicker and I want to save it in my CoreData. I create Attribute in my Entity with Binary Data type.
First of all, you need to convert UIImage to Data:
let data = UIImageJPEGRepresentation(image, 1.0)
After that set this data to property in the Entity in the perform method of NSManagedObjectContext:
context.perform {
entity.image = data
// Save context
}
I don't recommend you save UIImage to CoreData it's bad way. Just use https://github.com/Alamofire/AlamofireImage to cache an UIImage correct.

UIButton Background image is not set from Singleton Dictionary

again.
I've just finished a singleton example of a Dictionary with the following code
at the file Recipes.swift
static let sharedInstance = Recipes()
var imagesOfChef = [Int : chefImages]()
struct chefImages {
var objidChef: String!
var imageChef: UIImage!
}
And when a process is finished i have this code
let singleton = Recipes.sharedInstance
singleton.imagesOfChef = self.imagesOfChef
So the singleton has the same dictionary as the imagesOfChef has.
On the next view i want to access all the data of the Dictionary and set a background image of the button with one of the images that the Dictionary has.
So in the cellForItemAtIndexPath I have the following code
let test = userPointer.objectId
let otherReferenceToTheSameSingleton = Recipes.sharedInstance
for i in 0...otherReferenceToTheSameSingleton.imagesOfChef.count - 1 {
print(otherReferenceToTheSameSingleton.imagesOfChef[i]!.objidChef) //it prints the object id's of the Chef normally
if otherReferenceToTheSameSingleton.imagesOfChef[i]!.objidChef == test! {
print("done")
print(otherReferenceToTheSameSingleton.imagesOfChef[i]!.imageChef)
cell.avatarOutlet.setImage(otherReferenceToTheSameSingleton.imagesOfChef[i]!.imageChef, forState: .Normal) //but it doesnt set the Image as a background
}
}
So when the object id of the Chef matches the object id that is inside the Dictionary i want to set as background the image that is in the same row.
But it doesn't!
Although when the if statement is correct if you see i try to print the image and i get
<UIImage: 0x1582c9b50>, {60, 60}
How is it possible to set this image as background??!?!
Thanks a lot!
Set the Button type custom if it is created programmatically
let button = UIButton(type: UIButtonType.Custom) as UIButton
If it is from Stroyboard change the type there.

Updating a property in a struct inside an array

In my app I download a load of JSON.
I then store that as an array of structs and use that to populate a UITableView.
One of the properties of the struct is an NSURL for an image. Another property is an optional UIImage.
The struct has a mutating function downloadImage which uses the URL to download the image and store it in its property.
Like this...
struct SearchItem {
// other properties...
let iconURL: NSURL
var icon: UIImage?
mutating func downloadImage() -> Task<UIImage> {
let tsc = TaskCompletionSource<UIImage>()
NSURLSession.sharedSession().downloadTaskWithURL(iconURL) {
(location, response, error) in
if let location = location,
data = NSData(contentsOfURL: location),
image = UIImage(data: data) {
self.icon = image
tsc.setResult(image)
return
}
tsc.setError(NSError(domain: "", code: 1, userInfo: nil))
}.resume()
return tsc.task
}
}
The problem I'm having is this. (and I have been stumped by this in the past).
I have an array [SearchItem] that I use to populate the tableview.
In cellForRow I have the code... if let searchItem = items[indexPath.row]...
It then checks if the image is nil and downloads...
if let image = searchItem.icon {
cell.imageView.image = image
} else {
searchItem.downloadImage().continueOnSuccessWith(Executor.MainThread) {
_ in
tableView.reloadRowsAtIndexPaths([indexPath], withRowAnimation: .None)
}
}
But this never goes through to put the image into the cell. This is because the SearchItem is struct and so pass-by-value. So the search item that I am downloading the image for is not the same SearchItem as the one stored in the array.
How can I ensure that the image that is downloaded is then stored into the SearchItem inside the actual array?
Use classes.
You're getting a copy of searchItem in your cellForRow method. Whatever you do to this, will be done only to that copy. What you actually want is for the changes you make to that copy to be applied to the version in the array.
Therefore you want reference semantics, therefore use classes.
You could dance around re-inserting the updated copy into the original array if you liked, but what does that gain you besides a line of extra code and probably some other problems.
Structs are lightweight data objects that are not passed by reference, but instead copies itself as needed when you a) pass it to a new function, b) try and access it in a block. Arrays in Swift also work slightly differently than their Obj-C counterparts. When you have an Array of class objects the array will be a reference type, and you'll be able to achieve what you're trying to achieve here. But on the other hand if the Array is of Structs the array looses its reference semantics and uses copy-by-value instead.
This difference is really powerful when used appropriately, you can greatly optimise your code, make it run faster, have less errors produced by mutable object references having changes happen in multiple parts of your code, etc. But it's up to you as a developer to see where the gains of these optimisations are useful or where it makes sense to use objects instead.

Cannot assign value of type '[String : AnyObject]

I am using Xcode 7 and swift I get this error when run my app in my iPhone:
Cannot assign value of type [String : AnyObject] to type UIImage?
func imagePickerController(picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [String : AnyObject]) {
imgview.image = info
[UIImagePickerControllerOriginalImage]as?UIImage;
dismissViewControllerAnimated(true, completion: nil)
}
The problem is that you cannot split [] operator onto a separate line in Swift: square brackets need to be on the same line as the dictionary being dereferenced. Also don't forget to dismiss and release the picker.
picker.dismissModalViewControllerAnimated(true)
picker.release()
imgview.image = info[UIImagePickerControllerOriginalImage] as UIImage
Since Swift does not use mandatory semicolons to break down statements, you need to pay more attention to what goes onto which line. Your code is interpreted like this:
Assign info to imgview.image
Cast an array that consists of UIImagePickerControllerOriginalImage to UIImage
Obviously, this is not the effect that you were trying to get. Moving square brackets to the same line as info will fix this problem.
info is a dictionary, which is what [String : AnyObject] means. The keys of the dictionary are String's and the values can be any object. Yet, you wrote:
imgview.image = info
So, you assigned some dictionary to imgview.image, yet imgview.image is of type UIImage optional. Instead, you need something like:
let image = info[UIImagePickerControllerEditedImage] as! UIImage
imageView.image = image

Swift keep pointer/reference to object or another a pattern?

I am converting a project from another tool and language:
Suppose I have a
singleimagecache: UIImage;
I now pass this to a structure which does
var myimage: UIImage = singleimagecache;
Now, this struct is passed to a function that does some work.
This function determines another image should be cached. In my original code, it would simply use myimage and assign its content some other image-bitmap data. Since the object-reference itself was not changed (only its content) singleimagecache would still point to valid fresh new cache data.
However, this is not possible in Swift since UIImage requires to be reconstructed like this:
myimage = UIImage(...)
But doing that would leave singleimagecache with wrong data
So that leaves me the following options:
Any support in Swift for keeping references in sync?
Any support in Swift for keeping pointers to objects (that themselves possibly can be nillable)
Wrap UIImage inside another object that is persistant and use that.
There is no built-in Swift support for what you wish to do. I would just make a wrapper class with 2 UIImage properties. One would be myimage and the other would be singleimagecache. You could then use the didSet property observer on myimage to achieve the desired synchronization so that singleimagecache will always be up to date with myimage. didSet will be called everytime a new value is stored/set in the property.
class imageCache
{
var myimage:
= UIImage() {
didSet {
singleimagecache = myimage
}
}
var singleimagecache = UIImage()
}

Resources