Get path of button's image (iOS) - ios

I've created an UIButton subclass and I need to get the path of the image that the button has. I can write self.path but not self.imageView.image.path Any idea?

I don't believe that you can get the path. If you look at the api docs for UIImage, you can instantiate with a file, but by the time you have an instance the file is gone and all that's still there is the NSData.
This wouldn't be very efficient, but if you know the candidate files that were used to create the image, then perhaps you could hash the NSData, and compare with a hash of the NSData on the UIButton's UIImage?

Related

How to test if a UIImageView contains an image with a specific name using XCUITest?

I have a collectionView that has a bunch of cells that contain a single UIImageView in each cell. I want to test wether or not in each cell, the imageView's image matches the correct image name.
In the production code, I've added an accessibility identifier to the UIImageView example: "My Image View". I loop through an array of strings containing image names and set the cell's image in accordance to the index, example: ["image0.png", "image1.png", "image2.png"] so cells at index 0-2 would have those images respectively.
In my XCUITest file I'm trying something like this:
XCTAssert(cells.images["My Image View"].exists, "message here")
But this doesn't check if the cell's imageView has the right image. Can anyone suggest a better solution?
Some references I visited beforehand:
How to test UIImageView elements in iOS XCTest?
XCUIElement - Obtain Image value
I apologize if this question has been asked before, I couldn't find anything.
Edit:
I found a solution.
let image = cells.element(matching: , identifier: )
I didn't know that the identifier parameter actually uses the image name so If I pass the image name, I can assert the existence of the image.
let image = cells.element(matching: .image, identifier: "myImage.png")
this works. So when I loop through an array of strings containing the image name, I can also check if the cell at the index corresponding to the image index is correct.
I also forgot to mention that the images aren't being stored in assets, but are being fetched via json.
cesarmarch's answer below was the closest so I marked that as correct.
XCTest UI tests are designed to be written as functional tests, rather than checking that the display is correct. Since the image doesn't exhibit a behaviour for the UI test to observe, a UI test isn't the best tool for the job.
In this case, you should write unit tests to assert that the correct image is assigned to your image views, as unit tests will have access to the right level of information to allow you to inspect the data you pass to your view presentation layer and assert that the assigned image is the one you expect.
I just use something like
XCTAssert(cells.images["Image_Name_In_Resource_Directory"].exists, "message here")
to check if the current image is the good to use and it works fine.
All the images in the project are exported into the app bundle while building. Have a folder under your UI Testing group to contain all the expected images to be verified and a dummy image file.
var url = Bundle(for: AnyClass.self).url(forResource: "<ExpectedImageName>", withExtension: "<imageExtension png/jpg/etc>")!
let expectedImage = NSImage(contentsOf: url)!.tiffRepresentation!
url = Bundle(for: AnyClass.self).url(forResource: "<NameOfDummyImageFile>", withExtension: "png")!
try? cells.images["My Image View"].screenshot().pngRepresentation.write(to: url)
let actualImage = NSImage(contentsOf: url)!.tiffRepresentation!
XCTAssert(actualImage.elementsEqual(expectedImage), "Images are not same.")
The above code works for me.. Hope this will work for you too

How can I load Images from URL into an UIImage Array and use them in UIScrollView with Swift

I have a working UIScroll view with local Images in my app. I want however, that my Images will be downloaded and stored in Cache from a URL. I have seen several example libraries that do this like sdwebimage, kingfisher etc. but the examples use UITableview and cells. I am using a UIImage Array for my scroll view. What I actually want is that I download and cache my images and store them in a Array IconsArray = [icon1, icon2, icon3] where icon1 to icon3 are the downloaded images from URLs. How would I do this? Any nice tutorials out there or someone kind enough to show a rookie some code?
Thanks in advance
If you are downloading many images you will have memory problems, and your work will also get thrown away when your array goes out of scope, but what you probably would want to do, if you want to implement your proposed solution, is to use a dictionary rather than an array. It'll just make it much easier to find the image you're looking for. So you could implement the dictionary like this:
var images = [String : UIImage]()
For the key you can just use the URL string (easy enough solution) so accessing an image safely would look like this:
let urlString = object.imageUrl.absoluteString //or wherever you're getting your url from
if let img = self.images[urlString] {
//Do whatever you want with the image - no need to download as you've already downloaded it.
cell.image = img
} else {
//You need to download the image, because it doesn't exist in your dict
...[DOWNLOAD CODE HERE]...
//Add the image to your dictionary here
self.images[object.imageUrl.absoluteString] = downloadedImage
//And do whatever else you need with it
cell.image = downloadedImage
}
As I said, this has some downsides, but it's a quick implementation of what you're asking for.

XCUIElement - Obtain Image value

I have an variable that's of type .Image and class XCUIElement. Something like this:
var image = app.descendantsMatchingType(.Image).elementAtIndex(0)
Is there a way I can extract the actual image so I can compare it to another image?
I've tried caling the value method, but it returns a string. Casting it to a UIImage always fails.
I have had a conversation about this with the Apple Developer Tools evangelist recently. There is currently no way of accessing the actual image from an image view, button, etc. Similarly, there is no way to access other properties of views that might be of interest, like "isHidden" or "attributedText", etc. I was told that the engineers on the UI Testing team are interested in the use cases that people are wanting access to these properties for, so it would be very helpful -- both for them and for the other people who want this feature -- if you would file a bug report / feature request asking for it at https://bugreport.apple.com
As a tip regarding the "value" property on an XCUIElement, at least for now this appears to map to the "accessibilityValue" property of whatever view the XCUIElement is referencing. So if you set that accessibilityValue of a view you are interested in to contain some information you are interested in verifying, then this can possibly help in testing. Two things to be aware of though:
1) Even though the "value" property of an XCUIElement is of type "id", the type of the accessibilityValue property is "NSString". I don't know what would happen if you try to force some non-string value (like an image) into accessibilityValue and then try to retrieve it from the "value" property of XCUIElement, but I suspect it wouldn't work well. Partially because:
2) The accessibilityValue property of a view is actually used by Apple's VoiceOver feature for the vision impaired. When the value is set, it will be read out loud when the user taps on that element (which is why it's supposed to be a string).
I also covered the issue with not being able to access properties of view via XCUIElement in more detail here: http://www.danielhall.io/exploring-the-new-ui-testing-features-of-xcode-7
I know it may be not exactly what you're looking for, but I managed to write a test that checks if the visual representation of a UIImage on the screen has changed.
I'm using a screenshot() method of XCUIElement which returns an instance of XCUIScreenshot:
let myImage = XCUIApplication().images["myAccessibilityIdentifier"]
let screenshotBefore = myImage.screenshot()
//...
//do some actions that change the image being displayed
//...
let screenshotAfter = myImage.screenshot()
//Validating that the image changed as intended
XCTAssertNotEqual(screenshotBefore.pngRepresentation, screenshotAfter.pngRepresentation)
The screenshots will be the size of the image as rendered on the screen which may be different to the original image of course.
It's important to compare the PNG representations using the pngRepresentation property, but not the XCUIScreenshot objects because the two objects will always be different internally.
This technique can't test that the image displayed on the screen is exactly what is needed but at least can detect changes in the image.

swift, How to get currently displayed image file name from UIImageView [duplicate]

This question already has answers here:
UIImageView - How to get the file name of the image assigned?
(17 answers)
Closed 4 years ago.
I want to get the image file name which is currently displayed at UIImageView. I tried to get it as follow:
let currentImage = alien.image // !alien is my image view
println(currentImage?.description)
but it prints:
Optional("<UIImage: 0x7fa61944c3d0>")
You can't do this. Neither in swift nor objective-c.
The thing to do is to store the data you want to retrieve. That is... store the name somewhere and use that to load the image. Not the other way around.
So create a property something like imageName and then use that to load the image.
As a work around, for images that I need to reference at a later time, I use the restoration ID to store the image name.
I used restoration ID in this way so that I could connect multiple buttons to the same #IBAction and identify them based on the image name stored in the restoration ID and run logic about what I want to display or hide.
There might be better ways but this worked in a pinch.
I put the image name in as the restoration ID.
Here is where I designate the file for the image..
And I just copy that and put it in as the restoration ID.
(note: that is not what this was intended to be used for as it is really meant for customizing state reference but if that is not relevant to the purpose of your view, then it should work fine.)
Referenced in code when the button is selected.
//Connected to several onboarding buttons.
#IBAction func onBoardingButton(sender: UIButton) {
println(sender.restorationIdentifier)
}
RID printed out.
You can also tag your images and keep the reference to those images via the tag.
And the reference is just as easy.
#IBAction func onBoardingButton(sender: UIButton) {
println(sender.restorationIdentifier!)
println(sender.tag)
}
While it doesn't seem like we can discern what file was used to fill the imageview (that I know of and based on a little looking around myself) attaching hard references to a view (image, button, etc..) allows me to make the connection code side and figure out which image (or in my case button) is being used.

Are Images assigned in a xib cached?

If I assign an image to a UIImage view in a xib, is that image cached so that if I access the image using UIImage imageNamed: I am getting cached Image data?
I'm using iOS 5.1
UIImage imageNamed: does its own cacheing of any images you use. The first time you use it for a given image, it'll populate the cache, and subsequently it'll use the cached version.
UIImageView in Interface Builder takes a string to tell it what image to use. It appears that the object that is actually encoded in the Xib to represent the image is a private class called UIImageNibPlaceholder, which contains a private NSString variable called runtimeResourceName. It's this class that implements the initWithCoder: method which is used when the system is loading objects from a xib.
So, the question is, inside UIImageNibPlaceholder's initWithCoder:, does it use the imageNamed: function of UIImage? I think it's reasonable to assume that it does, since the thing stored in the xib is the string runtimeResourceName, and the system is turning that string into an actual image when loading the xib.
This post on the Apple developer forums seems to clarify the point (under NDA so I can't copy it here). I couldn't find any publicly accessible information on the subject.

Resources