UIButton Background image is not set from Singleton Dictionary - ios

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.

Related

How to UITest UIProgressView?

Situation:
I want to UI-test my progress view and see if it's progress has increased.
What I've tried:
By using a breakpoint in my UI-test and using the po print(app.debugDescription), I can successfully see and access the UIProgressView element.
It's called:
Other, 0x6080003869a0, traits: 8589935104, {{16.0, 285.5}, {343.0, 32.0}}, identifier: 'progressView', label: 'Progress', value: 5%
I access it with let progressView = secondTableViewCell.otherElements["progressView"], which works, as .exists returns true.
Now, to check progress, the description above hints at the 'value' property, that is currently at 5%. However, when I try progressView.value as! String or Double or whichever, I cannot seem to get the property as it isn't NSCoder-compliant.
Question:
Is it possible to UI-test a UIProgressView and use it's progress value?
My final custom solution:
Using the value property (when casting to String) somehow does work now. As I wanted to check if progress increased over time, I strip the String to get the numeric progress in it to compare. Here is my solution I use now:
// Check if progress view increases over time
let progressView = secondTableViewCell.otherElements["progressView"]
XCTAssert(progressView.exists)
let progressViewValueString = progressView.value as! String
// Extract numeric value from '5%' string
let progressViewValue = progressViewValueString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
// Let progress increase
sleep(3)
let newProgressViewValueString = progressView.value as! String
let newProgressViewValue = newProgressViewValueString.components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
XCTAssert(newProgressViewValue > progressViewValue)
XCUIElement conforms to XCUIElementAttributes which gives you access to a value property of type Any?
The actual type of value at runtime depends on which kind of UI element you are querying. In case of a UIProgressView it is of type __NSCFString, which is a concrete subclass of NSString. Which means you can safely cast it to String:
This works (provided that you set your progress view's accessibility identifier to "progressView"):
func testProgressView() {
let app = XCUIApplication()
app.launch()
let progressView = app.progressIndicators["progressView"]
// alternative (if the above query does not work):
// let progressView = app.otherElements["progressView"]
let currentValue = progressView.value as? String
XCTAssertEqual(currentValue, "5 %")
}
Weirdly in some cases the progressIndicator query does not work. In that case you can try a otherElements query (see comment in above code)

iOS UI Test: Get image filename (Swift)

My question is about getting the filename of image of the UIImage that is used in a UIImageView.
Here is my sample code:
// Using image from UIImageObject
imageView1.image = myUIImage
// Using image from XAssets
imageView2.image = UIImage(named: "myImageName")
In UI Tests, how can I get the name of the image file?
The expected resoult would be:
"myUImageObject" // For imageView1
"myImageName" // For imageView2
Is there any way to get this value?
Thanks everyone!
Unfortunately you can't do that, however there's an easy workaround, try something like this:
let myImageView = UIImageView()
myImageView.image = UIImage(named: "anyImage")
myImageView.restorationIdentifier = "anyImage" // Same name as image's name!
// Later, in UI Tests:
print(myImageView.restorationIdentifier!) // Prints "anyImage"
Basically in this solution you're using the restoration identifier to hold the image's name, so you can use it later anywhere. If you update the image, you must also update the restoration identifier, like this:
myImageView.restorationIdentifier = "newImageName"
I hope that helps you, good luck!
Swift 4
Declare Outlet
#IBOutlet weak var m_SetName_Img: UIImageView! //Image is already set image from Assets File
Declare Function
extension UIImageView {
func getImageName() -> String {
if let image = self.image, let imageName = image.accessibilityIdentifier {
return imageName
} else {
return "nil"
}
}
}
Use
print(self.m_SetName_Img.getImageName())
You can use:
imageView2.image?.imageAsset?.value(forKey: "assetName")
assetName is private API, so officially out of bounds for the App Store, but for testing it should be just fine.

for loop animation not working correctly?

I have copied 5 image files into my project, have cast them to the UIImage class from strings (not included below), created an array for them, and tried to loop through that array when I click the updateIMAGE button, to essentially create a little animation. The file in the UIImageView is frame1, but when I try press the button in the simulator it loops straight to the frame5.
var imageArray: [UIImage] = [frame1, frame2, frame3, frame4, frame5]
#IBOutlet var imageView: UIImageView!
#IBAction func updateIMAGE(sender: AnyObject) {
for image in 0..<imageArray.count {
var im = imageArray[image]
imageView.image = im
println(im)
}
}
You can iterate through an array and add an UIImage to array and outside the loop assign that array to the animationImages property of UIImageView, set up duration and run animation:
var array: NSMutableArray = []()
for image in 0..<imageArray.count {
{
array.addObject(imageArray[image])
}
imageView.animationImages = array;
imageView.animationDuration = 1.5
imageView.startAnimating()
To be much more efficient, iOS will combine multiple drawing operations into a single operation, which is 99.99% of the time what developers and their customers want. If you want an animation, you will have to write some code that does animations.
PS. You can iterate directly through an array, you don't need an index variable.

How to find value of UIImage called in ViewDidLoad, pass to another function in Swift

I am using a simple function to call a random image when a view controller is loaded.
override func viewDidLoad() {
super.viewDidLoad()
var randomtest = ReturnRandom()
mainImage.image = UIImage(named: randomtest)
}
I want a button's action to be based on what image was displayed. For example
#IBAction func Button1(sender: AnyObject) {
switch randomtest {
case 1: //Do something here
case 2: //Do something different here
default:
}
However I can not figure out how to get the value of "randomtest" out of ViewDidLoad. I also can not seem to create the random number outside the ViewDidLoad then pass the variable in. Sorry I'm new to all this, iOS development is a long way away from php...
The reason I was having trouble declaring the result of my function as a instance variable is that my function is also an instance function. I can not call it, there has been no instance. So this
class ViewController : UIViewController {
var randomtest: Int = ReturnRandom();
Will return a "Missing argument for parameter #1 in call"
For more details please check out this very helpful thread on setting initial values. Since my function was so simple I just computed the property while setting the initial value, no need for an additional class level function.
dynamic var randomtest:String {
let imageNumber = arc4random_uniform(3)
var imageString = String(imageNumber)
return (imageString)}
Hope this helps someone.

How can I set the value of this variable?

I want to change the value of a UIImage view.
This is what I've got so far.
import UIKit
import Foundation
struct imageViews {
var Slope1ImageView: UIImage?
var slopeStatus = dataValues()
func setSlope1Image(slopeStatus1: Int) -> UIImage {
var image: String
switch slopeStatus1 {
case 0:
image = "NotWorkingStatus"
default:
image = "WorkingStatus"
}
var statusImage = UIImage(named: image)
return statusImage
}
}
This my setup.
I have a file which gets an object from Parse.
This will either be 0 or 1.
I then assign the 0 or the 1 to a variable in a struct.
In my code above I have created a instance of this struct.
I have then created a function which will take in a variable from my struct and check if it has the value of zero, it then sets the variable image to the respective image. If it doesn't it sets it to a different image.
How do I set the variable of Slope1ImageViews to the image selected by the function in this way.
Slope1ImageView = setSlope1Image(slopeStatus.SlopeStatus1)
each time I try I get an error along the lines of
cannot assign to "Slope1ImageView" in "self"
I'm at my wits end!
Any help would be greatly appreciated.
I think your problem is with Slope1ImageView. If the first letter is uppercased, Swift assumes you're referring to a class. Furthermore, you need to assign the local to either a variable or a constant. Structs should also have the first letter uppercased. Assuming everything else is set up correctly, you probably just need to do something like this.
struct ImageViews {
// existing code...
}
var instanceOfStruct = ImageViews()
var slope1imageView: UIImage = instanceOfStruct.setSlope1Image(slopeStatus.SlopeStatus1)
There's a lot going on here, I'll touch on some.
Declaration
You shouldn't be using a struct. Images are rather large objects in general and you don't want them to be copied across your app. They should remain reference types and be in a class. Structs/Classes should also be capitalized to adhere to common practice, while properties should be lower case. You also have your name as a plural which implies that it is an array, it shouldn't be this way. Also, don't name something imageView unless its an imageView. On that same line, don't name something image if it's a string. Also, don't prefix a function with set unless it sets something. Your function returns something, so a get prefix is probably better. I feel like you want to set the image within self, so let's do that. So first step is to change this:
struct imageViews {
var Slope1ImageView: UIImage?
var slopeStatus = dataValues()
func setSlope1Image(slopeStatus1: Int) -> UIImage {
var image: String
switch slopeStatus1 {
case 0:
image = "NotWorkingStatus"
default:
image = "WorkingStatus"
}
var statusImage = UIImage(named: image)
return statusImage
}
}
To this:
class SlopeStatus {
var slope1Image: UIImage?
var slopeStatus = dataValues()
func setSlope1Image(slopeStatus1: Int) {
var imageString: String
switch slopeStatus1 {
case 0:
image = "NotWorkingStatus"
default:
image = "WorkingStatus"
}
slope1Image = UIImage(named: image)
}
}
Assignment
You're trying to assign a UIImage to a Class with this:
Slope1ImageView = setSlope1Image(slopeStatus.SlopeStatus1)
With the changes above, it should probably be
var slopeStatusImageObject = SlopeStatus()
slopeStatusImageObject.setSlope1Image(slopeStatus.SlopeStatus1)

Resources