How to check if a button has this image - ios

I want to check if myButton has a named image.
I try this but it doesn't work
if (myButton.currentImage?.isEqual(UIImage(named: "ButtonAppuyer.png")) != nil){
print("YES")
} else {
print("NO")
}
and this too doesn't work
if myButton.currentImage?.isEqual(UIImage(named: "ButtonAppuyer.png")){
print("YES")
} else {
print("NO")
}

Here is what I came up with in Swift 3.0.
if let myButtonImage = myButton.image(for: .normal),
let buttonAppuyerImage = UIImage(named: "ButtonAppuyer.png"),
UIImagePNGRepresentation(myButtonImage) == UIImagePNGRepresentation(buttonAppuyerImage)
{
print("YES")
} else {
print("NO")
}
This could be cleaned up a lot.
extension UIButton {
func hasImage(named imageName: String, for state: UIControlState) -> Bool {
guard let buttonImage = image(for: state), let namedImage = UIImage(named: imageName) else {
return false
}
return UIImagePNGRepresentation(buttonImage) == UIImagePNGRepresentation(namedImage)
}
}
Then use it
if myButton.hasImage(named: "ButtonAppuyer.png", for: .normal) {
print("YES")
} else {
print("NO")
}

in swift 4.2 and Xcode 10.1
buttonOne.image(for: .normal)!.pngData() == UIImage(named: "selected")!.pngData()

You can convert the button's image and the named image to NSDatas and compare the two data objects:
let imgData1 = UIImagePNGRepresentation(buttonImage)
let imgData2 = UIImagePNGRepresentation(namedImage)
let equal = imgData1 == imgData2
Note that this will only work if the two images are completely identical (e.g. come from the same source file); if one is a scaled down version of the other, it won't work.
Also, it should be mentioned that this can be a pretty expensive operation and should not be run frequently.

There is no way to retrieve the image name from a UI element. You will need to store the value you want to retrieve in another location.
For instance, you could create a custom subclass of UIButton that contains an additional property to store the image name or other identifying data.

if let ButtonImage = myButton.image(for: .normal),
let Image = UIImage(named: "ButtonAppuyer.png"),
UIImagePNGRepresentation(ButtonImage) == UIImagePNGRepresentation(Image)
{
print("YES")
} else {
print("NO")
}

if myCell.followButton.currentImage.isEqual(UIImage(named: "yourImageName")) {
//do something here
}

Related

UIImage not changing image because of EXC_BAD_ACCESS crash, why?

I have this conditional that results in a UIImageView being changed depending one what side a coined "flipped" (Int.rand(0...1). I am not sure why it is crashing at this particular spot, as before the program gets to this point it could change the exact same UIImageView with another image asset. The image asset I want to change it to does exist in the asset folder. It's just confusing why it is crashing at this particular instance.
func changeField(coin: Int){
lowerField.isUserInteractionEnabled = false
upperField.isUserInteractionEnabled = false
firstP1.isHidden = true
firstP2.isHidden = true
if coin == 0{
lowerField.image = UIImage(named: "Red_Attacker")
upperField.image = UIImage(named: "Blue_Defender")
if userSettings.float(forKey: "Timer_Slider") == 0{
gameP1()
}else{
startTimer(slider_Value: userSettings.float(forKey: "Timer_Slider"), coin: coin)
}
}else{
lowerField.image = UIImage(named: "Blue_Defender")
upperField.image = UIImage(named: "Red_Attacker")
if userSettings.float(forKey: "Timer_Slider") == 0{
gameP2()
}else{
startTimer(slider_Value: userSettings.float(forKey: "Timer_Slider"), coin: coin)
}
}
}
this shows where it specifically throws the exception
Anyone have any idea why it is crashing at this spot? Would appreciate the help!
first make sure that you have an image with this name
second thing try to put it in dispatchQueue:
DispatchQueue.main.async {
lowerField.image = UIImage(named: "Red_Attacker")
upperField.image = UIImage(named: "Blue_Defender")
}
DispatchQueue.main.async {
lowerField.image = UIImage(named: "Blue_Defender")
upperField.image = UIImage(named: "Red_Attacker")
}

textField Editing Changed not reacting fast enough (Asynchronous calls)

I have a textfield that queries a firebase database for existing users and then display a UIImage according to if the user is available or not. The problem is that once the async code loads, the textfield doesn't react on changed value.
example. If i type 12345 as a username, i don't query the database. Everything ok. If i add a 6 it queries firebase and it shows me the user is free. if i press backspace and have 12345 the textFieldChanged is triggered again, and database is not queried. All OK.
but the problem is, when i have 12345, and i type 6 and very fast back so i have 12345, the query is running and shows me the available icon (because the back was pressed very fast). Is this because of the Simulator or is it a real problem and can i be fixed easily ?
my code:
#IBAction func textFieldChanged(_ sender: UITextField) {
if let username = usernameInputText.text, username.count > 5 {
checkIfUserExists(username: username) { doesExist in //(2)
if doesExist! {
self.completeSignupButton.isEnabled = false
self.ifAvailableImageView.image = UIImage(named: "Close")
} else {
self.completeSignupButton.isEnabled = true
self.ifAvailableImageView.image = UIImage(named: "Check")
}
}
} else {
ifAvailableImageView.image = UIImage(named: "Close")
self.completeSignupButton.isEnabled = false
}
}
func checkIfUserExists(username: String, completion: #escaping (Bool?) -> Void) {
spinner.startAnimating()
self.ifAvailableImageView.image = nil
let docRef = db.collection("users").document(username)
docRef.getDocument { (document, error) in
if error != nil {
self.spinner.stopAnimating()
completion(nil)
} else {
self.spinner.stopAnimating()
if let document = document {
if document.exists {
completion(true)
} else {
completion(false)
}
}
}
}
}
You can just compare the username being processed with the current text in the text field and not process the result if it not the same because you only want to process the latest one.
#IBAction func textFieldChanged(_ sender: UITextField) {
if let username = usernameInputText.text, username.count > 5 {
checkIfUserExists(username: username) { doesExist in //(2)
// Check if current text and the completion being processed are for the same username
if username != sender.text {
return
}
if doesExist! {
self.completeSignupButton.isEnabled = false
self.ifAvailableImageView.image = UIImage(named: "Close")
} else {
self.completeSignupButton.isEnabled = true
self.ifAvailableImageView.image = UIImage(named: "Check")
}
}
} else {
ifAvailableImageView.image = UIImage(named: "Close")
self.completeSignupButton.isEnabled = false
}
}

iOS: Set setImageInputs of image slideshow to array of images

I'm using an image slideshow from here:
iconArr = [UIImage(named: "home-min")!,UIImage(named: "category-
min")!,UIImage(named: "settings-min")!,UIImage(named: "contact us-min")!,UIImage(named: "about us-min")!,UIImage(named: "logout")!]
I need to make this array as an image source.
for image in self.iconArr {
let img = image
self.SlideShow.setImageInputs([ImageSource(image: img)])
}
But that is not working, how can I do that?
you should try this way for sure, because you reset inputs in your for-loop
var imageSource: [ImageSource] = []
for image in self.iconArr {
let img = image
imageSource.append(ImageSource(image: img))
}
self.SlideShow.setImageInputs(imageSource)
As sooper stated, can be done this way
let imageSources = self.iconArr.map { ImageSource(image: $0) }
I found a solution from this url [https://stackoverflow.com/a/50461970/5628693][1]
Below is my code working fine :
var imageSDWebImageSrc = [SDWebImageSource]()
#IBOutlet weak var slideshow: ImageSlideshow!
Add below viewDidLoad()
slideshow.backgroundColor = UIColor.white
slideshow.slideshowInterval = 5.0
slideshow.pageControlPosition = PageControlPosition.underScrollView
slideshow.pageControl.currentPageIndicatorTintColor = UIColor.lightGray
slideshow.pageControl.pageIndicatorTintColor = UIColor.black
slideshow.contentScaleMode = UIViewContentMode.scaleAspectFill
// optional way to show activity indicator during image load (skipping the line will show no activity indicator)
slideshow.activityIndicator = DefaultActivityIndicator()
slideshow.currentPageChanged = {
page in
print("current page:", page)
}
let recognizer = UITapGestureRecognizer(target: self, action: #selector(Dashboard.didTap))
slideshow.addGestureRecognizer(recognizer)
} // now add below func
#objc func didTap() {
let fullScreenController = slideshow.presentFullScreenController(from: self)
// set the activity indicator for full screen controller (skipping the line will show no activity indicator)
fullScreenController.slideshow.activityIndicator = DefaultActivityIndicator(style: .white, color: nil)
}
And last step i was getting json data from below alamofire request
Alamofire.request(url, method: .post, parameters: data, encoding: JSONEncoding.default).responseJSON { response in
if(response.value == nil){
}
else {
let json2 = JSON(response.value!)
switch response.result {
case .success:
self.indicator.stopAnimating()
if let details = json2["imgs"].array {
for dItem in details {
let img = dItem["img"].stringValue
let image = SDWebImageSource(urlString: self.imgurl+img)
self.imageSDWebImageSrc.append(image!)
}
self.slideshow.setImageInputs(self.imageSDWebImageSrc)
}
break
case .failure( _):
break
}
}
}
Thanks dude :) happy coding

tableView images randomly disappearing

I am modifying my paid for app to a free with IAP.
Some group types are free and some will need to be paid for.
On the tableView controller, there is a padlock UIImageView that displays each "locked" item if it is a part of a locked group.
When someone buys that group, or all, that padlock is meant to disappear. This padlock is not a part of the code that prevents the user from seeing the details as I have that code somewhere else and it works fine.
Initially, "Padlock" displays accurately. However, If I scroll up and down on the tableView, the padlocks will randomly disappear.
How to prevent this?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
//
// We need to fetch our reusable cell.
//
let cell: UITableViewCell = tableView.dequeueReusableCell(withIdentifier: Resource.SpeciesCell)!
//
// Get all of the components of the cell.
//
let specieImage: UIImageView = cell.viewWithTag(Resource.SpeciesImageTag) as! UIImageView
let specieName: UILabel = cell.viewWithTag(Resource.SpeciesNameTag) as! UILabel
let specieGenus: UILabel = cell.viewWithTag(Resource.SpeciesGenusTag) as! UILabel
let specieFamily: UILabel = cell.viewWithTag(Resource.SpeciesFamilyTag) as! UILabel
// Set our name, family and genus labels from our data.
//
specieName.text = self.species[(indexPath as NSIndexPath).row].specie
specieFamily.text = ""
specieGenus.text = self.species[(indexPath as NSIndexPath).row].speciesSubgroup
// **** Adding Padlock Begins HERE ****
let padLock: UIImageView = cell.viewWithTag(Resource.SpeciesCategoryLabelTag) as! UIImageView
padLock.image = UIImage(named: "PadlockIcon")
padLock.alpha = 0.7
let speciesGroupFreeArray: Array<String>
let speciesGroupVertebratesArray: Array<String>
let speciesGroupInvertebratesArray: Array<String>
speciesGroupFreeArray = ["eels", "Mammals", "Annelids", "Bivalvians", "Cephalopods", "Cool oddities", "Crustacean", "Echinoderms", "Hydrozoans", "Isopods"]
speciesGroupVertebratesArray = ["Fish", "Sharks", "Rays", "Reptilia", "Syngnathiformes"]
speciesGroupInvertebratesArray = ["Corals", "Gastropods"]
let fishesPurchased = UserDefaults.standard.bool (forKey: "ReefLife5Fishes")
let sharksPurchased = UserDefaults.standard.bool (forKey: "ReefLife6Sharks")
let nudisPurchased = UserDefaults.standard.bool (forKey: "ReefLife7Nudis")
let turtlesPurchased = UserDefaults.standard.bool (forKey: "ReefLife8Turtles")
let seahorsesPurchased = UserDefaults.standard.bool (forKey: "ReefLife9Seahorses")
let coralsPurchased = UserDefaults.standard.bool (forKey: "ReefLife4Corals")
let vertebratesPurchased = UserDefaults.standard.bool (forKey: "ReefLife3Vertebrates")
let invertebratesPurchased = UserDefaults.standard.bool (forKey: "ReefLife2Invertebrates")
let fullPurchased = UserDefaults.standard.bool (forKey: "ReefLife1Full")
let categoryName = self.species[(indexPath as NSIndexPath).row].group
if fullPurchased == true {
padLock.isHidden = true
} else if speciesGroupVertebratesArray.contains(categoryName) {
if vertebratesPurchased == true {
padLock.isHidden = true
} else {
if categoryName == "Fish" {
if fishesPurchased == true{
padLock.isHidden = true
} else{
}
} else if (categoryName == "Sharks" || categoryName == "Rays" ) {
if sharksPurchased == true{
padLock.isHidden = true
} else{
}
} else if categoryName == "Syngnathiformes" {
if seahorsesPurchased == true{
padLock.isHidden = true
} else{
}
} else if categoryName == "Reptilia" {
if turtlesPurchased == true{
padLock.isHidden = true
} else{
}
}
}
} else if speciesGroupInvertebratesArray.contains(categoryName) {
if invertebratesPurchased == true {
padLock.isHidden = true
} else {
if categoryName == "Corals" {
if coralsPurchased == true{
padLock.isHidden = true
} else{
}
} else if categoryName == "Gastropods" {
if nudisPurchased == true{
padLock.isHidden = true
} else{
}
}
}
}
if speciesGroupFreeArray.contains(categoryName) {
padLock.isHidden = true
}
// **** Adding Padlock Ends HERE ****
//
// We now need to set our photo. First, we need to fetch the photo based on our specie
// id.
//
let photos = AppDelegate.getRLDatabase().getSpeciePhotos(self.species[(indexPath as NSIndexPath).row].id)
//
// Set the image for our UIImageView.
//
if photos.isEmpty != true
{
specieImage.clipsToBounds = true
specieImage.contentMode = .scaleAspectFill
specieImage.image = UIImage(named: photos[0].name)
// specieImage.image = UIImage(named: photos[0].name)?.resizeTo(specieImage.bounds)
}
else
{
specieImage.image = UIImage(named: Resource.UnknownImage)?.resizeTo(specieImage.bounds)
}
//
// Return our new cell.
//
return cell
}
Please try replace this
if speciesGroupFreeArray.contains(categoryName) {
padLock.isHidden = true
}
to
padLock.isHidden = speciesGroupFreeArray.contains(categoryName)
Your code only ever sets padlock.isHidden = true. If you get a recycled cell where the padlock is already hidden, there's nothing to unhide it.
You need to explicitly set the padlock isHidden state in all cases.
Given your somewhat contorted code for setting the isHidden property, the simplest way to fix your current code would be to set padlock.isHidden = false At the beginning of your cellForRowAt() method. Then, if none of the cases set isHidden to true, it will always be unbidden, even in a case where you are reconfiguring a recycled cell where the padlock was hidden.
EDIT:
This a key take-away for managing table views and collection views in iOS. Always assume that a cell comes to you with all views set to a non-default state. Your code always needs to explicitly set every view to a specific state.
Think of a table view cell as a paper patient info form at a doctor's office where the office recycles the forms, and doesn't erase the info left by the previous patient. You always have to erase the info left by the previous patient. If you don't have an allergy to peanuts, it's not enough to simply not check that box. You have to erase the previous check marks and other info, or the previous patient's info will get mixed up with yours.
That's what's happening with your padlock.isHidden state. You're assuming it starts out in the default state, but it may not.

How would I write this typedef enum from objective c to swift?

Below, I have the objective-c code which is used for tinder style animation effect , inspired by - https://github.com/ngutman/TinderLikeAnimations/tree/master/TinderLikeAnimations .
Objective-c
typedef NS_ENUM(NSUInteger , GGOverlayViewMode) {
GGOverlayViewModeLeft,
GGOverlayViewModeRight
};
- (void)setMode:(GGOverlayViewMode)mode
{
if (_mode == mode) return;
_mode = mode;
if (mode == GGOverlayViewModeLeft) {
self.imageView.image = [UIImage imageNamed:#"button1"];
} else {
self.imageView.image = [UIImage imageNamed:#"button2"];
}
}
I am trying to replicate the same in swift. This is what I have in swift -
enum GGOverlayViewMode : Int {
case GGOverlayViewModeLeft
case GGOverlayViewModeRight
}
func setMode(mode: GGOverlayViewMode){
// if (_ mode == mode) {
// return
// }
//
// _mode = mode;
if(mode == GGOverlayViewMode.GGOverlayViewModeLeft) {
imageView.image = UIImage(named: "button1")
} else {
imageView.image = UIImage(named: "button2")
}
}
But somehow its not making sense to how would I be handling the typdefs here.
Any help is appreciated.
Thanks
In Swift each enumeration has its own member values, so you don't have to give
them a unique prefix as in (Objective-)C. A typical definition would be
enum GGOverlayViewMode {
case Left
case Right
}
Also you don't have to specify an underlying "raw type" (such as Int), unless
you have other reasons to do so.
Instead of a custom setter method you would implement a property observer.
didSet is called immediately after the new value is stored, and has an implicit
parameter oldValue containing the old property value:
var mode : GGOverlayViewMode = .Right {
didSet {
if mode != oldValue {
switch mode {
case .Left :
imageView.image = UIImage(named: "button1")
case .Right:
imageView.image = UIImage(named: "button2")
}
}
}
}
I think in swift, your function will look like this.
enum GGOverlayViewMode : Int
{
case GGOverlayViewModeLeft
case GGOverlayViewModeRight
}
func setMode(mode: GGOverlayViewMode){
switch mode
{
case .GGOverlayViewModeLeft:
imageView.image = UIImage(named: "button1")
case .GGOverlayViewModeRight:
imageView.image = UIImage(named: "button2")
}
}

Resources