swift compare multiple images to an array of images - ios

I have 2 UIImageViews connected to an array of images
I'm trying compare both once they are displayed but doesn't seems to work.
I tried using imageArray[Image Literal] and also imageArray[image1.png, image2.png, image3.png, image4.png, image5.png]
I'm not sure what im doing wrong.
im not looking for the code although it may help but what im looking is for a someone to guide me to the right direction
#IBOutlet weak var 1ImageView: UIImageView!
#IBOutlet weak var 2ImageView: UIImageView!
let imageArray = [image1.png, image2.png, image3.png, image4.png, image5.png]
func any() {
if (1ImageView != nil) && (2ImageView != nil) && isEqual(image1.png) {
print("match!")
} else if ...// more if statements
…last if statement} else {
print(“no match!”)
}
#IBAction func buttonPressed(_ sender: IUButton) {
any()
}
If this is not possible is there a way to assign an identifier to each of the images inside the array..
sorry for the extra question.
there is one answer on comparing 2 images using NSData but Im not sure how to implement it to an array.
thanks and sorry but the newbie question.

image.isEqual(image) seems to be unreliable, despite what documentation says. If you don't need to make a pixel perfect comparison, converting image to a data and comparing those would be sufficient.
let image1 = UIImage(named: "image1.png")
let image2 = UIImage(named: "image2.png")
let imageData1 = image1?.pngData()
let imageData2 = image2?.pngData()
if imageData1 == imageData2 {
print("images are the same")
} else {
print("images are different")
}
Looking for a specific image inside an array can build on that:
// array of images referencing image files within an Xcode project
// it's not the best idea to force unwrap those, but for the sake of simplicity
let imageArray = [UIImage(named: "image1.png")!,
UIImage(named: "image2.png")!,
UIImage(named: "image3.png")!,
UIImage(named: "image4.png")!,
UIImage(named: "image5.png")!]
func anySimilarImages() {
// find first image which is the same as 1ImageView's
let 1ImageViewImage: UIImage? = imageArray.first { (image) -> Bool in
return image.pngData() == 1ImageView.image?.pngData()
}
// find first image which is the same as 2ImageView's
let 1ImageViewImage: UIImage? = imageArray.first { (image) -> Bool in
return image.pngData() == 2ImageView.image?.pngData()
}
if 1ImageViewImage != nil && 2ImageViewImage != nil {
print("both images were found")
}
else if 1ImageViewImage != nil {
print("first image was found")
}
else if 2ImageViewImage != nil {
print("second image was found")
}
else {
print("no image was found")
}
}

Related

Swift: UIButton.currentImage is not working comparing image name

I'm trying to check the image name in the UIButton like this:
#IBAction func buttonTapped(_ sender: Any) {
if xcodeButton.currentImage == UIImage(named: "xcode") {
print("xcode image")
}
}
But I have a break point in the if statement and this is the output:
po xcodeButton.currentImage
▿ Optional<UIImage>
- some : <UIImage:0x6000011a93b0 named(main: xcode) {500, 500}>
but if I compare it
po xcodeButton.currentImage == UIImage(named: "xcode")
false
Any of you knows why the comparison is returning false? or how can compare the name of the image in UIButton?
I'll really appreciate your help.
You should use isEqual(_:) From Docs scroll to Comparing Images section
let image1 = UIImage(named: "MyImage")
let image2 = UIImage(named: "MyImage")
if image1 != nil && image1!.isEqual(image2) {
// Correct. This technique compares the image data correctly.
}
if image1 == image2 {
// Incorrect! Direct object comparisons may not work.
}
None of these solutions were working for me. So I used pngData to compare images:
let image1Data = UIImage(named: "MyImage")?.pngData()
let image2Data = UIImage(named: "MyImage")?.pngData()
if image1Data == image2Data {
// It compares data correctly
}

SwiftUI - Check If Image Exist

I am attempting to execute code if an image exist.
The issue is I am unable to capture the state of empty image call.
The result is I get an empty image, but would rather put a placeholder image if possible.
func procImage(inName: String) {
switch (inName) {
case inName:
imageName = inName.lowercased()
default:
imageName = "blank"
}
}
This check is easy but you need to be sure that default image always exists.
func getSafeImage(named: String) -> Image {
let uiImage = (UIImage(named: named) ?? UIImage(named: "Default.png"))!
return Image(uiImage: uiImage)
}
Try this code:
func procImage(inName: String) -> UIImage {
if let confirmedImage = UIImage(named: inName) {
return confirmedImage
} else {
return UIImage(named: "Default_Image.png")!
}
}
Thanks all for contributing.
The solutions on offer did not quite work in my case except for Moreno's solution, but offered a path to my solution.
I did not need to store the result of the check, but just validate the existence of the file.
So this is what I came up with which worked.
This may not be the optimal solution, so improved code will be welcomed.
func procImage(inName: String) {
let imageConvertToLowercase = inName.lowercased()
if getMember.firstName.lowercased() == imageConvertToLowercase {
if (UIImage(named: imageConvertToLowercase) != nil) {
imageName = imageConvertToLowercase
} else {
imageName = "blank"
}
}
}

Saving multiple images to Parse

So I have an array of images I've accessed from my xcassets for demonstration purposes. There are 150 images I'm trying to save to my parse server at one time using parse frameworks. Here is the code I have so far. The problem I have is my app cpu goes to 100% in the tests and drops to 0. Also the images aren't saving to parse. I was hoping someone could help me find an efficient way to save 150 images to parse.
var imageNameList: [String] {
var imageNameList2:[String] = [] //[NSMutableArray]()
for i in 0...149 {
let imageName = String(format: "pic_%03d", Int(i))
imageNameList2.append(imageName)
}
return imageNameList2
}
#IBAction func Continue(_ sender: Any) {
for imageName in imageNameList {
var objectForSave:PFObject = PFObject(className: "Clo")
let object:UIImage = UIImage(named: imageName)!
let tilesPF = imageNameList.map({ name in
let data = UIImagePNGRepresentation(object as! UIImage)!
let file = PFFile(data: data)
let tile = PFObject(className: "Tile")
tile["tile"] = file
})
objectForSave["tiles"] = tilesPF
objectForSave.saveInBackground(block: { responseObject, error in
//you'll want to save the object ID of the PFObject if you want to retrieve a specific image later
})
}
}
The trouble is that the tight for-loop launches all of those requests concurrently causing some part of the http stack to bottleneck.
Instead, run the requests sequentially as follows (in my best approximation of Swift)...
func doOne(imageName: String, completion: (success: Bool)->()) {
var objectForSave:PFObject = PFObject(className: "Clo")
let object:UIImage = UIImage(named: imageName)!
// ... OP code that forms the request
objectForSave.saveInBackground(block: { responseObject, error in
success(error == nil)
})
}
func doMany(imageNames: Array<String>, completion: (success: Bool)->()) {
if (imageNames.count == 0) return completion(YES)
let nextName = imageNames[0];
self.doOne(imageName:imageNames[0] completion: {(success: Bool) -> Void in
if (success) {
let remainingNames = imageNames[1..imageNames.count-1]
self.doMany(imageNames: remainingNames completion:completion)
} else {
completion(NO)
})
}
In English, just in case I goofed the Swift, the idea is to factor out a single request into it's own function with a completion handler. Build a second function that takes an array of arguments to the network request, and use that array like a to-do list: do the first item on the list, when it completes, call itself recursively to do the remaining items.

is it correct to send UIImage between two controllers?

Is it appropriate to send UIImage between two Uiviewcontrollers?
I'm working on assignment 4 of CS193P Spring - Smashtag.
There I have to implement Mention Table View (It's kind of additional data of tweet: mentions, hashtags, images, urls). I have to place images to appropriate cell there. For that purpose I already download it. After that If user tap on one of that images It should segue to another UIViewController where user can zoom and scroll image.
In many examples which I've seen, people send url of image and fetch it again and again (for mention controller and the same image for another one). I think It decreases perfomance. So I send UIImage object between controllers.
But is it correct?
// MARK: - Navigation
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if segue.identifier == Storyboard.SearchSegue {
if let svc = segue.destinationViewController as? SearchResultsTableViewController {
if let cell = sender as? TextTableViewCell {
if let text = cell.hashtagLabel.text {
if text.hasPrefix("#") || text.hasPrefix("#") {
svc.searchText = text
}
}
}
} else if let svc = segue.destinationViewController as? ImageViewController {
if let cell = sender as? ImagesTableViewCell {
svc.image =
}
}
}
}
svc.image is var:
var image: UIImage? {
get {
return imageView.image
}
set {
imageView.image = newValue
imageView.sizeToFit()
scrollView?.contentSize = imageView.frame.size
}
}
and cell.imageVar
var imageVar: UIImage? {
get {
return imageField.image
}
set {
imageField.image = newValue
spinner.stopAnimating()
}
}
fetch function
private func fetchImage () {
if let u = url {
spinner?.startAnimating()
dispatch_async(dispatch_get_global_queue(QOS_CLASS_USER_INITIATED, 0)) {
let contentsOfURL = NSData(contentsOfURL: u)
dispatch_async(dispatch_get_main_queue()) {
if u == self.url {
if let imageData = contentsOfURL {
self.imageVar = UIImage(data: imageData)
} else {
self.spinner.stopAnimating()
}
}
}
}
}
}
That only make sense if you're using different image sizes. For instance, if you're using the image in a cell, you should use a small image, a thumbnail, to make the download faster. And then when you see the detail and want to zoom the image, you should use a bigger image (so you have to retrieve it using the url).
But if you only have one image size, it's totally correct to pass an UIImage through view controller.
You can think of caching the image. You can save the image in document directory and use its link to load in other places. One thing however you need to keep in mind is that you need to keep a track of how long you want the images to be cached this way, and a mechanism for deleting them. If you want the image only for one session you can even choose to use NSCache.

iOS not saving all images

In my app I have a button. If you tap it you can download a couple of images (13) to your photo library.
I created an array that holds the images, named "1", "2", "3", "4", etc. like this: (I checked, the array holds all 13 images)
var myPhotos: NSMutableArray = []
for i in 1...13 {
let img = UIImage(named: "\(i)")!
myPhotos.addObject(img)
}
I then save all the images to the photo library:
var photo = UIImage()
var j = 0
for photo in myPhotos {
j++
UIImageWriteToSavedPhotosAlbum(photo as! UIImage, nil, nil, nil)
}
print(j)
print("done")
In the photo library of my simulator there are all the 13 images. When running this on my iPad that number varies a lot, from like 8 to 12 but never 13. That's why I put j there. It proves that the loop runs all the way through the array (j is 13 in the console) and "done" is also being printed.
What is the problem here?
Thanks in advance :)
this should work:
class ViewController: UIViewController {
var myPhotos = [UIImage]()
var savedPhotos = 0
override func viewDidLoad() {
super.viewDidLoad()
// setup photos
for i in 1...13 {
let img = UIImage(named: "\(i).jpg")! // remove the ".jpg" for you to work
myPhotos.append(img)
}
// save photos
saveNextPhotoToPhotosAlbum()
}
func saveNextPhotoToPhotosAlbum() {
if let photo = myPhotos.first {
UIImageWriteToSavedPhotosAlbum(photo, self, "image:didFinishSavingWithError:contextInfo:", nil)
}
}
func image(image: UIImage, didFinishSavingWithError error: NSErrorPointer, contextInfo:UnsafePointer<Void>) {
if error == nil {
print("saved \(++savedPhotos). photo")
myPhotos.removeFirst()
saveNextPhotoToPhotosAlbum()
}
}
}
in my case i used .jpg images so maybe you have to remove the extension in the for loop to make it work for you!

Resources