Swift UIKit: Unable to update UIButton X when pressing UIButton Y [duplicate] - swift

I was trying to make a simple tic-tac-toe app in Swift, so I set up 9 buttons with tags from 1 to 9 and call setImage to set noughts or crosses. This is working as intended.
The problem comes when trying to reset the board, where I call this piece of code:
for i in 1..<10 {
if let button = view.viewWithTag(i) as? UIButton {
button.setImage(nil, for: .normal)
}
}
This should remove the image from the button, but it does nothing. The button is set to Custom in the storyboard, and the tags are indeed assigned as they should. I also tried getting an outlet for one of the buttons and calling setImage(nil, for: .normal) in that one and it didn't work either.
I even created a new project with just a button where I call setImage, and it is indeed working for non-nil images but not with nil as value.
Has Apple changed the way of removing images? Another question(When button pressed, button.setImage(nil) doesn't work) seems to have the same problem, but if I work with isHidden I can no longer click on the buttons, and it should not be the workaround, looks very hacky to me.
Is this a bug on iOS? Did the implementation change or something?
Thank you.

This seems like it may be a bug in iOS 15, but it still works if use the new UIButton Configuration API you set its configuration's image instead:
button.configuration?.image = nil
Be sure to also configure your button's image through its configuration property when you want it to have an image on iOS 15, too

Related

Swift Cocoa manipulate design of titlebar buttons

I'm currently developing a Swift/Cocoa application with XCode 12.3 and Swift 5.
I'd like to manipulate the design of the close button in the titlebar of a NSWindow.
I've already tried to change the design using
self.window?.standardWindowButton(.closeButton)?.layer. ... = ...
But this approach seems not to be working - at least for me. Do you have any ideas on how to make it possible?
You need to set wantsLayer to true. Standard window buttons are regular NSButtons with an NSCell inside them. To customize the and not have the original button block the view, you either need to remove the cell and use the layer or just create a custom one.
Note that when removing or setting your own button cell, its action selector will reset, so you need to keep sure that the buttons still do what you want them to.
Here's the code in Objective C, but it should be easy enough to translate into Swift:
NSButton *button = [self standardWindowButton:NSWindowCloseButton];
button.wantsLayer = YES;
button.layer.backgroundColor = NSColor.greenColor.CGColor;
NSCell *cell = [[NSCell alloc] initTextCell:#"?"];
[button setCell:cell];
Result:

Swift - How to check which image is assigned to button

I'm trying to check if an image is assigned to a button. So far I use this:
if MyButton.currentImage.isEqual(UIImage(named: "Black")) {
//do something here
}
But I get error message:
Use of unresolved identifier"MyButton"
even though I set the label of the button to MyButton.
Seems like you do not have MyButton defined in your code. You should create a variable of type UIButton in which you store the button (connect it with outlet in storyboard or initialize it with code). Setting a label to the button as you mentioned will not do anything.

Mac OS - Change Status Item Button Image

I want to update the image when the user clicks something in the application but I can't get it to work.
The status item with the menu is defined in the AppDelegate. I am trying to update the image in the ViewController with this piece of code which I think should work:
AppDelegate().statusItem.button?.image = NSImage(named:NSImage.Name("icon-orange"))
No errors are showing up, but turns out it still doesn't work, so is it possible to change the image or am I doing something wrong?
AppDelegate() creates a brand new instance which is not the delegate class in Interface Builder.
You need the real reference:
(NSApp.delegate as! AppDelegate).statusItem.button?.image = NSImage(named:NSImage.Name("icon-orange"))

iPhone UIButton buttonType always evaluates to 0?

Whenever I execute the code below I always get button type = 0 no matter what I specify for buttonWithType. Does anyone know an explanation for this behavior? I'm trying to distinguish button based on their type obviously without success since the buttonType property appears to be broken (or useless). As always thanks very much for any enlightenment you may provide!
UIButton *button = [[UIButton buttonWithType:UIButtonTypeDetailDisclosure] retain];
button.frame = frame;
NSLog(#"###################### LeftCalloutButtons - buttonWithTitle(73) - button type = %d",button.buttonType);
I encountered cases when UIButton properties (backgroundColor in my case) would have bogus value until the button is added to a view. Try querying the property once the button is on the screen.
EDIT: just saw another example of this behavior. This time it was about UISwitch.on. If I set it to YES right after alloc/init, it's not displayed as on. If I set it to YES in the viewDidLoad handler, it works as expected.
Apparently there's some lazy loading going on in the UIKit.
I have just verified the same issue with iOS 4.3.2 and Xcode 4.0.2. When looking at the internal structures of the UIButton instance in the debugger, the private struct _buttonFlags contains the unsigned int buttonType which is set to the correct value (non-zero in my case).
However, the debugger reports in response to print (int) [control buttonType] always 0.
In conclusion the method buttonType is broken and I will report this as a bug to Apple. I think it won't harm if other people who tried to use this method do the same.

iPhone SDK 2: Programmatically adding an Info Button

I am trying to add an info button to my app to provide custom help.
Instead of adding the button to the nib and linking the event (touchUpInside) to the controller, I decided to add the button programmatically. The button shows up. When I add the target event handler to be executed when the button is touched, it does not work. That my method(doHelp) is not being called on touching the button.
When I debugged it, the event is not registered with the button! Although the code does not throw any exceptions.
Here is the code snippet FROM the view:
// Create a Button to get Help
UIButton *helpButton = [UIButton buttonWithType:UIButtonTypeInfoDark ] ;
buttonRect = helpButton.frame;
// CALCulate the bottom right corner
buttonRect.origin.x = rect.size.width - buttonRect.size.width - 8;
buttonRect.origin.y = rect.size.height - buttonRect.size.height - 8;
[helpButton setFrame:buttonRect];
[helpButton addTarget:self action:#selector(doHelp:) forControlEvents:UIControlEventTouchUpInside];
[helpButton setEnabled:TRUE];
[self addSubview:helpButton];
........
// Another METHOD ELSEWHERE in the VIEW object
-(void)doHelp:(id)Sender
{
[self setHelpNeeded:TRUE];
[self setNeedsDisplay];
}
What am I doing wrong please?
I have looked at the SDK help and samples and am really flummoxed!
Am hoping another pair of eyes will help! :-)
This code snippet is in the View Object in case you need to know.
I just added the doHelp to help the first 2 responders... thanks.
**UPDATE 6/4/09 ** -
I have been trying all night and nothing worked. I think there is something wrong in the way I have set up the method selector as my method never gets called. Everything else looks fine. Even using a NIB file does not work. I have tagged the button, retrieved it and added the method selector but to no avail. There is something fundamental which I am doing wrong... Argh!!!
Any ideas, anyone?
Resolved it finally!!! and learnt something in return. Did cost me a few days to figure this out.
The reason my UIButton object was not working was because I found that in case of a UIIMageView object:
"initWithImage: This method adjusts the frame of the receiver to match the size of the specified image. It also disables user interactions for the image view by default."
AND my UIButton had been assigned as a subview of a UIImageView control !!!
There was no errors / warnings. It just gets disabled quietly.
Solution: Created a container UIView object which now contains the UIImageView AND the button so that the button appears as overlayed on the Image but it is actually a sibling of the image and a subview of the dummy container UIView.
It's been awhile, but I think your addTarget needs to take the object that contains the doHelp: selector, like so:
[helpButton addTarget:self action:#selector(doHelp:)];
assuming somewhere in that same View you have:
- (void)doHelp: { }
passing nil to addTarget means that you're sending that selector to no recipient.
The problem is your addTarget:nil there. The selector you gave it for action is just a message it'll send to its target. You didn't give it a target, so it doesn't know what to do with that message. You probably want to pass in self instead of nil there.
I came across this while googling for a solution to the same problem. At least with the 3.x SDK, all you have to do is set the UserInteractionEnabled property of the UIImageView to YES.
Thanks for posting your discovery about the problem, I wouldn't have even thought to look at that one.
I had a similar problem where Buttons were outside of the view and did not receive tap messages
what helps is to set background colour of the parent view, to see that button is outside of it:
...
[buttonParentView addSubview: myButton];
buttonParentView.backgroundColor = [UIColor cyanColor];