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.
Related
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
I'm trying to implement a very simple test, but I'm stuck with XCUIElementQuery.matching(identifier:) method. I think querying UIImageViews is not working as expected, but not sure why.
I have these two settings set for views:
Label:
UIImageView:
And I have this test:
func testRecording() {
XCTAssertEqual(app.staticTexts.matching(identifier: "label").count, 2)
XCTAssertEqual(app.images.matching(identifier: "accept").count, 1)
}
where I'm querying for these two views (Label with id label and UIImageView with id accept). From here: app is simply defined as class property like this: let app = XCUIApplication().
So, this is what screen looks like:
This means that this test should pass since there are two staticTexts with id label and one image with id accept on screen. staticTexts are being successfully queried, but it is failing when matching(identifier:) tries to query image with id accept:
I tried to query with many things, like:
app.images.
app.tables.
app.tables.images.
app.tables.cells.images.
app.buttons. (also marked as Button in Traits part of the Accessibility settings)
app.staticTexts. (also marked as Static Text in Traits part of the Accessibility settings)
but no luck... Is there anything that I'm doing wrong here, or missing something?
OK, since I'm in the QA team, I haven't looked much to the dev code. But when I did, I found the answer.
UIImageView that is used for displaying check mark is never being used from .xib file, but instead is always allocated a new instance like this:
indicatorView = UIImageView(image: #imageLiteral(resourceName: "arrow_marked_ok_small"))
meaning that new accessibility options are set with initializer call, so that old UIImageView instance that has accessibility options from .xib file I posted in first two images is being overridden.
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.
I have given a UIButton a tag of 1 inside the interface builder attributes section.
I then want to access the tag value of that button once it is pressed, so far I have done this but it is coming back as 0.
#IBAction func attractiveMinus(sender: AnyObject) {
println(sender.tag) //sender.tag comes back as zero.
}
I am not sure if this is the correct way of finding out the tag of a button can somebody please say where i'm going wrong?
thanks
That should work, so I'd double check that you've updated the tag of the right button. Make sure that the updated IB files are being included in the build by wiping your derived data. Sometimes when you make a really small change like that, Xcode will use the previous version of the Storyboard/Xib that it has cached.
Also, since you know the sender is going to be a button, you can use UIButton in place of AnyObject to get the most out of Swift's type safety.
I have an iPhone application that displays details of local businesses. I read the business details from a .csv file to first show all businesses in a UITableViewController, and then depending on the selection, show the details for each business in a UIViewController.
All information is displaying and working as intended, except for my images - they are not displaying. I have created an IBOutlet for them same as for all the other labels and this is how I set the image in the UIViewController in viewDidLoad():
self.businessImage.image
= [UIImage imageNamed:businessDetailContent.imageName];
Where businessDetailContent.imageName is a NSObject that holds the business' details.
All images are also imported and present. When I NSLog after the above code, I can see the image is present, but its not showing up on my UIViewController.
And here is how the information in the .csv file looks
ID, name, address, tel, email, URL, description, hotel_someHotelName
Where hotel_someHotelName is the name of the image file (hotel_someHotelName.jpg).
I have tried adding the .jpg extension to the end of hotel_someHotelName in .csv but still no image.
Some of the images are low quality, so may this be the issue?
You are saying:
self.businessImage.image = [UIImage imageNamed:businessDetailContent.imageName];
And no image is appearing in your interface. So there are three possibilities:
[UIImage imageNamed:businessDetailContent.imageName] is nil
self.businessImage is nil
self.businessImage is a nonnil image view, and you are successfully assigning it an image, but that image view is not in your interface (or constraints are resizing it to zero size so that it is effectively invisible)
The first two may be readily tested by careful logging. One way to test the third possibility is to give the image view a colored background (set its backgroundColor; you can do this in Interface Builder too). If you still don't see it, that's the problem.
Just found my issue. In my .csv file, the image name had a space after the image name. When I removed this space (purely found by accident), the images are working fine.
Thanks for all the help all the same