How to set button image to nil in Swift? - ios

In a reset button where I want to reset my game when I try to set my image to nil Xcode displays this error:
Could not cast value of type 'UIView' (0x106c26e88) to 'UIButton'
(0x106c2cf68).
This is my code:
var button : UIButton
for var i = 0; i < 9; i++ {
button = self.view.viewWithTag(i) as! UIButton
button.setImage(nil, forState: .Normal)
}

The best way to do this is set the contents to the path of the file as empty or invalid
let image = UIImage(contentsOfFile: "")

You can insert nil image to your button as
let btnCheckMarkImage = UIImage(CGImage: nil)
checkBoxbtn.setImage(btnCheckMarkImage, forState: UIControlState.Normal)

For anyone who finds this issue and is trying to solve the problem from the title,
button.setImage(nil, for: .normal)
should produce the desired result.
(Added my answer to this post as it was the first result in Google.)

By the error, the problem seems to be that one of the tagged views you are trying to cast as UIButton isn't really an UIButton class object

I found my view tag = 0 and this is what make the app crash

Related

What is the difference between `UIbutton.setImage` and changing `UIbutton.imageView`?

What is the difference between UIbutton.setImage and changing UIbutton.imageView?
buttonA.imageView?.image = UIImage(named: "name")
buttonA.setImage(UIImage(named: "name"), for: .normal)
When I try to use setImage and then try to get it's position using frame.origin.x, the position returned are not what I expected and so I used .imageView?.image approach. But when I use that, I observed that clicking on the button changes the image for a brief time before continuing.
the function offers you the ability to set different icons for various states
setImage(imageNormal, for: .normal) //normal state
setImage(disabledImage, for: .disabled) //disable UI representation
UIButton.imageView according to documentation read-only property https://developer.apple.com/documentation/uikit/uibutton/1624033-imageview
For some clarification...
If you set the .image property directly:
buttonA.imageView?.image = UIImage(named: "name")
You have not informed the button class that it has a new image property.
The same thing applies to setting the title:
buttonA.titleLabel?.text = "My Title"
That will change the text of the title label, but only until the next UI update... at which point UIKit will use the value assigned via:
buttonA.setTitle("Button A", for: .normal)
That's why it's important to use both .setImage(...) and .setTitle(...) instead of setting the property itself.

Setting a button image depending on another variable? Swift

so I'm very new to swift. I currently have 16 buttons all set to individual outlets box1,box2,box3 etc.
Each box I have set a tag and what I am trying to do is set the image of a particular box based off another integer variable to determine which box I'm changing.
So say I do a calculation and index = 4.
Is there a way I can then set box(index).setImage?
I understand this probably isn't the best way to do it or even possible, maybe I can set each button to an array of objects instead? Any tips would be great.
If you want to set the image of button through some tag then you don't need any outlets for the buttons.
You can change your button image by finding the button through viewWithTag() property.
Here is the code
var button = self.view.viewWithTag(Your_Calculated_Index) as! UIButton
button.setImage(Your_Image, for: .normal)
You can try this. You need to create an array for the button.
#IBOutlet var allbtns: [UIButton]!
for buttons in allbtns{
if buttons.tag == 4{
print("Button 4 ");
buttons.setImage(UIImage(named: "imagname"), for: UIControlState.normal)
}else{
print("Other buttons except 4 ");
}
}

How to overlay a UIButton (close) button on top of a UIWebView?

I have been looking and trying to solve an issue I have with a UIWebView for iOS.
I have a very small app which just loads my website the source code lives at https://github.com/pjuu/iotter.
On the site when a user clicks on a posted image it load the image URL in to the web view. This leaves them stranded and unable to get back to other parts of the site.
What I want to do is display an (x) button in the top right hand corner (no matter what screen rotation is in use) and have perform the back operation in the browser.
I know this question isn't a code issue as I'm fine to sort of the Swift code part of it. I just could not for the life of me work out how to add the button programmatically and have it display over the webview.
The only tutorials I could find involved creating a tool bar to perform these type of actions which I think would take up to much space when looking at an image.
The question is very simple:
Is this possible?
If so how would I go about creating the button?
I am going to check the request.path parameter with regex to only show it if it matches an image URL.
Apologies if this isn't fitting enough for SO. I am happy to move the question or post on another site.
Thank you for any help in advance. I am not a mobile developer so using XCode and the storyboard stuff is a world away from vim for me.
REFERENCE:
1) CGRectMake: https://developer.apple.com/library/ios/documentation/GraphicsImaging/Reference/CGGeometry/#//apple_ref/c/func/CGRectMake
2) UIWebViewDelegate:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIWebViewDelegate_Protocol/#//apple_ref/occ/intfm/UIWebViewDelegate/webView:shouldStartLoadWithRequest:navigationType:
SOLUTION:
1) Create the "X" UIButton:
// Define the UIButton
let button = UIButton(type: UIButtonType.System) as UIButton
let image = UIImage(named: "name") as UIImage?
button.frame = CGRectMake(self.view.frame.width - 60, 30, 35, 35)
button.setTitle("Test Button", forState: UIControlState.Normal)
button.setImage(image, forState: .Normal)
button.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
self.view.addSubview(button)
//Hide the UIButton
button.hidden = true
2) Detect when an imageUrl is opened and make the "X" UIButton appear:
// This function is triggered every time a request is made:
optional func webView(webView: UIWebView, shouldStartLoadWithRequest request: NSURLRequest, navigationType: UIWebViewNavigationType) -> Bool {
let string = request.URL
if string.rangeOfString(".png") || string.rangeOfString(".jpg")|| string.rangeOfString(".jpeg"){
// code to make cross appear
// for example:
self.button.hidden = false
}
}
3) Finally, you will need to create the method that closes the page when the "X" UIButton is tapped:
func btnPressed(sender: UIButton!) {
if(webview.canGoBack) {
//Go back in webview history
webview.goBack()
} else {
//Pop view controller to preview view controller
self.navigationController?.popViewControllerAnimated(true)
}
}
N.B.:
In the lines:
let image = UIImage(named: "cross.png") as UIImage?
button.setImage(image, forState: .Normal)
We are setting the UIButton to be the image of a cross.
You need to add a cross image to your XCode project and set the "cross.png" String to the exact name of your image: "nameOfImage.fileType".
Simple one line solution.
Create a desired "close" button in storyboard, or programmatically.
Then, just send your WebView to the back of all current views displayed in your view controller:
view.sendSubviewToBack(yourWebView)
Now, all views (including any buttons you create) will be displayed on top if it. Just be sure to add this line after all of your desired views are created.

Could not cast value of type

I am creating a Tic Tac Toe app. When the game resets, all the Xs and Os UIButton images should return to nil. Each space in the board is tagged from 0 to 8.
var buttonsToClear : UIButton
for var i = 0; i < 9; i++ {
buttonsToClear = view.viewWithTag(i) as! UIButton
buttonsToClear.setImage(nil, forState: .Normal)
}
Everything worked fine until I added a Navigation Bar. Now I get the error message
"Could not cast value of type '_UINavigationBarBackground' (0x107e2f2a0) >to 'UIButton' (0x107e357e0).
(lldb)
I am absolutely certain that my new Navigation Bar has a tag of "10".
What else could be triggering this message?
You should not use 0 tag, due to 0 is default and you can get any view (in this case the background of the navigation).
Tag the views starting by 1.
You are logically right and your code will work perfectly.
You are getting the error
"Could not cast value of type '_UINavigationBarBackground'
(0x107e2f2a0) >to 'UIButton' (0x107e357e0). (lldb)
Because, when your for loop runs, the first index will be zero i.e. i = 0,
buttonsToClear = view.viewWithTag(i) as! UIButton
will become
buttonsToClear = view.viewWithTag(0) as! UIButton
So in this case you are trying to get the view with tag value 0.
UINavigationBarBackground also has tag value 0.
Note:
1. when system finds two view with same tag value, and you are trying to get view using viewWithTag: it will return first view.
2. Every View Has default tag value 0.
3. Just drag UILabel or UIView in storyboard or XIB and check its tag value.
So in your case it will return UINavigationBarBackground instead of UIButton. So you can't type-cast UINavigationBarBackground into UIButton.
Solution of your Error :
Never give tags starting from 0.
Try to give tags starting for some value like 1000.
so your first button will have tag 1000, next will have 1001, then 1002 and so-on.
write your for loop as below.
var buttonsToClear : UIButton
for var i = 1000; i < 1009; i++ {
buttonsToClear = view.viewWithTag(i) as! UIButton
buttonsToClear.setImage(nil, forState: .Normal)
}
You must be able to see the stack trace to see where this is being triggered? In any case, the obvious solution is to run this in the debugger, turn on exception breakpoints and see what's going on.
And as Jose says, don't use Tag 0.
You need a new approach that doesn't rely on only using tags to identify your subviews
The problem is, your loop is coming across a private property on UINavigationBar, _UINavigationBarBackground. Because you can't set the tag on this, it will have the default tag of 0. Therefore you will attempt to send a UIButton function to it.
I would simply loop through your subviews and check if a view is of type UIButton, and then check it's tags (be sure still not to use tag 0, as that is the default tag) before removing it. That way you are 100% sure that you've gotten the right subview.
var buttonsToClear : UIButton
for view in view.subviews { // Loop through subviews
if let button = view as? UIButton { // Check if UIButton
if button.tag > 0 || button.tag < 10 { // Check tags
buttonsToClear = button
buttonsToClear.setImage(nil, forState: .Normal)
}
}
}

Check UIButton already exists or not in Swift

I found Objective-C coding for this topic. But the problem is that most of the classes and functions in Objective-C is deprecated in swift programming language.
I am using a UIButton inside a UITableView with flagForAction[Boolean Value]. So what i want to achieve is that if the UIButton is created once , there is no need to recreate it. So for that i need to check whether the UIButton already exists or not. Somebody suggested me the concept of tag for this, applying a particular tag to this UIButton and checking that is exist on the view or not. But i don't know how to do that.
Setting a tag:
myButton.tag = 1234 // some unique value, probably better to define as an enum or constant
Retrieving a view by tag (likely in cellForRowAtIndexPath):
if let myButton = tableviewCell.viewWithTag(1234) { // change tableviewCell for whatever your tableview cell variable name is
// myButton already existed
} else {
// TableviewCell doesn't contain a myButton, so create one here and set the tag as above
}
in swift 2.0
for view in myview.subviews {
if let btn : UIButton = view as? UIButton {
// access button here, either tag or title etc..
}
}
I am using view as example. You can also identify a button with accessibilityIdentifier property of the button, if you dont want to use tag proprerty of button.
For example :
var button = UIButton(frame: CGRectMake(0, 0, 100, 44))
button.accessibilityIdentifier = "button 1"
self.view.addSubview(button)
Here, i created a button with accessibilityIdentifier "button 1"
While creating the next button, i will check in the subview if it contains the button with accessibilityIdentifier "button 1", as below
var subviews : NSArray = self.view.subviews
for button : AnyObject in subviews{
if(button .isKindOfClass(UIButton)){
if(button.accessibilityIdentifier == "button 1"){
println("Button Already Exists")
}else{
println("Create new button")
}
}
}

Resources