I'm working in Swift and I'm trying to create a simple IBAction that puts an image (that I've already loaded in my assets) into a UIImageView once a button is clicked.
I've control-dragged and hooked everything up and yet I'm getting this error:
"cannot convert expressions type '()' to type 'UIImage!'"
I'm a beginner so please explain all answers thoroughly.
My code:
#IBAction func colorBtnClicked(sender: UIButton) {
colorsPanel.image = "Red_colors_panel"
}
First of all you need to pass an UIImage to the .image property but there is a String object and this cause the error.
To read image from your project bundle you need to do it the the following way:
colorsPanel.image = UIImage(named: "Red_colors_panel.png") // and do not forget the extension
Related
I'm now learning to make an audio recorder app. Basically, I want to add a tap gesture to a UIView to trigger/stop the recording. After triggering my recorder, the image should be changed to another one. My question is:
Am I supposed to control drag two #IBAction functions or only one? How to distinguish the "trigger" and "stop" action? My guess is I may only need one function, and at the beginning of it, I check the image name: if it's the recording icon or the stop icon, and do something accordingly. However, I cannot find the property of UIImage to identify the image it contains.
I'm new to ios so this may not be a good question, but please bear with me. By the way, I'm doing this using interface builder.
You do this by using highlightedImage and isHighlighted properties of UIImageView. And you can do this by using single IBAction
In the viewDidLoad method :
yourImageView.image = UIImage(name:"RecordImage/TriggerImage")
yourImageView.highlightedImage = UIImage(name:"StopImage")
You can set these images in the interface builder too. As you can see in the following image you need set images for both Image and Highlighted properties.
Inside your action method:
yourImageView.isHighlighted = !yourImageView.isHighlighted
if yourImageView.isHighlighted
{
//so now the UIImageView shows stop image that means we are in recording mode
// do the actions that are to be done in recording mode like start recording updating other UI etc
}
else
{
//so now the UIImageView shows Record/Trigger image that means are in normal mode or not recording
// do the actions that are to be done in normal mode like stop recording (if required )updating other UI etc
}
You only need one IBAction for the same and you can check for the image through following code inside the action:
if yourImageView.image == UIImage(named: "yourImageName") {
//perform some action here
} else {
//perform some action here
}
Step1 - declare a property in ViewController class to check the status of button
if is checked = true //recording is going on
if false //recording is stopped
//declaration in ViewController class
var isChecked = false
Step 2 - add a button imageView and Assign its button action as below
#IBAction func BottomImageBtnAction(_ sender: UIButton) {
isChecked = !isChecked
if isChecked {
//here şet image as stop
}
else {
//here set image as Start
}
}
I am using a UIImageView to change the image of the user. Currently the user has the option to remove the already present image. For this i am having a UIButton named "Remove photo" and in the action the code is written as:
#IBAction func removeUserPhoto(_ sender: UIButton) {
self.profilePhoto.image = UIImage (named: "defaultProfilePic")
self.photoChanged = true
let imageData: Data = UIImagePNGRepresentation(profilePhoto.image!)!
tempProfileImage = imageData
self.removePhoto.isHidden = true
}
When I click on the remove image the image is set to the defaultProfilePic but after few seconds the image view again shows the older image which the user has removed.
Note: No API call has been called yet.
The screenshots:
After clicking the remove button:
Few seconds after it again changes back to the older image automatically.
Why is this happening? And I found viewDidLayoutSubviews is calling twice or more.
I'm using Xcode 8.3 Beta.
You should remove image something like,
yourImageView.image = UIImage.init(named: "your place holder image name")
I mean assign your place holder image to your imageview! That's it! No need to take two imageviews!
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
I am trying to make a UIImageView named rDot tappable with tapGesture. When the image view rDot is tapped I want a different UIImageView on a different viewController, named wCircle to turn red. The problem is the code runs, but when I tap rDot the other image wCircle doesn't turn red.
override func viewDidLoad() {
super.viewDidLoad()
let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(imageTapped(tapGestureRecognizer:)))
rDot.isUserInteractionEnabled = true
rDot.addGestureRecognizer(tapGestureRecognizer)
}
func imageTapped(tapGestureRecognizer: UITapGestureRecognizer)
{
let wCircle = UIImageView(image: UIImage(named:"wCircle")?.withRenderingMode(.alwaysTemplate)) //error here
wCircle.tintColor = UIColor.red
}
In the context of Swift code, EXC_BAD_INSTRUCTION usually means you’ve hit a compiler trap, that is, an undefined instruction inserted into the code by the compiler because of a bug detected at runtime. The most common cause of these are:
failure to unwrap an optional — This can be a forced unwrap (!) or an implicit unwrap (accessing an implicitly unwrapped optional that’s nil).
array out of bounds
a failed forced cast (as!), either because the value was a nil optional or because the value was of the wrong type.
Check if wCircle is not nil.
Check if the outlet is properly connected.
make sure your image assets has an image exactly named "wCircle" case sensitive ,
again, in assets not in project bundle , i think UIImageView couldn't be initialized because an image with "wCircle" does not exist in assets
The way you init your UITapGestureRecognizer is incorrect.
Try
UITapGestureRecognizer(target: self, action: #selector(ViewController.imageTapped(tapGestureRecognizer:)))
Replace ViewController with your controller's class name
Make sure your object wCircle is present and initialize successfully
What is "wCircle" ? UIImage has no property called tintColor, if you want change image's color change his container UIImageView's tintColor
I've only been working with Swift and Xcode 6 for a few weeks, but I'm already working on an idea I have for an app. The part of the app I'm trying to work on would go like this:
1) User has a grid of buttons, which each do something different when tapped
2) User can tap a gear button on the bottom right of the view and then will have a new view presented modally, a makeshift settings pane (labels and switches). If the switch by the label of the name of the button is off, than that button is hidden.
3) User hits a Save button (which currently has NOTHING to do with NSUserDefaults or anything to do with actually saving features once the app is closed, it's CURRENTLY really just a back button) and any switches which are turned off make their respective button outlets hidden.
However, the actual project runs like this:
1) Works perfectly
2) When I tap the gear, the settings pane appears, as planned. I can also slide switches all around, but when I tap the save button, the app crashes and I get "fatal error: unexpectedly found nil while unwrapping an Optional value (lldb)" in the console.
Here's my code:
This is part of the first view controller with the buttons on it:
#IBAction func soundButton(sender: AnyObject) {
var soundID: SystemSoundID = 0
let soundFile: String = NSBundle.mainBundle().pathForResource("Sound", ofType: "wav")!
let soundURL: NSURL = NSURL(fileURLWithPath: soundFile)!
AudioServicesCreateSystemSoundID(soundURL, &soundID)
AudioServicesPlaySystemSound(soundID)
}
Above is an action which plays a sound when a button is pushed.
Now here's the outlet for the button and one for the border for it:
#IBOutlet var soundOutlet: UIButton!
#IBOutlet var soundRingOutlet: UIImageView!
In the storyboard, I have a tab bar controller and two views (ViewController and ViewControllerTwo), to access the settings view (SettingsViewController) I made a button with an image of a gear on it in the lower right hand corner, which is connected to the settings pane by a modally presented segue. HERE'S PART OF THE CODE FOR THE SettingsViewController:
//The switch
#IBOutlet var soundSwitch: UISwitch!
HERE'S WHERE THE ISSUE IS:
#IBAction func saveButton(sender: AnyObject) { if soundSwitch.on{
(presentedViewController as! ViewController).soundOutlet.hidden = true} else {(presentedViewController as! ViewController).soundOutlet.hidden = false
dismissViewControllerAnimated(true, completion: nil)
}
The issue is from the second instance of "presentedViewController" to "false"
Very frustrating problem, I've been working on this for hours, swapped code around, researched this, but nothing seems to work. There is obviously something I'm missing, after all, this is just exchanging data between views.
UPDATE: I've changed the two "presentedViewController"s in my problem with "presentingViewController"s instead. I got this error message in the console: "Could not cast value of type 'Buttons.TabBarViewController' (0x10d590d90) to 'Buttons.ViewController' (0x10d590e10).
(lldb)"
"Buttons" would be the project name.
presentingViewController is your tabBarViewController, while presentedViewController is what you are expecting to be your ViewController that is being presented, but infact this variable is nil because at the point in time you clicked this button, the modal viewcontroller hasnt set the presentedViewController variable for some reason, so the variable is actually nil, and when you trying to go as! ViewController on a nil variable, you are trying to cast nil to something it cant be so you get the crash, you'll have to find some other way to get hold of your viewcontroller that will be presented
Red, most of this looks OK. Just a couple of tips.
You don't have to duplicate your variable declarations.
let soundURL: NSURL = NSURL(fileURLWithPath: soundFile)!
Swift will infer your type in this case by your assignment.
As others have mentioned, use descriptive class names for your controllers. It will save you a lot of time when you're trying to figure out the purpose of the class. We've all been there 8>).
You will need to instantiate an instance of your controller that holds the soundOutlet property. Something like:
let dvc = YourControllerClass()
dvc.soundOutlet.hidden = true
dvc.modalTransitionStyle = UIModalTransitionStyle.FlipHorizontal
dvc.modalPresentationStyle = UIModalPresentationStyle.Popover
dvc.presentViewController(YourViewController, animated: true, completion: nil)
If you have not figured it out, post more of your implementation.
Good Luck.
I'm quite new to the iOS platform, but am already an experimented Android dev.
I'm experiencing a weird issue in Swift, we cannot reproduce in Objectice-C. We are designing our interfaces by hand, without using the Interface Builder, to have more flexibility.
We are getting a EXC_BAD_ACCESS on the mentioned line in our custom UIViewController. While the question seems to have been asked many times on StackOverflow, I either haven't found a solution written in Swift or a solution which was working properly and a really similar problem.
override func viewDidLoad() {
super.viewDidLoad()
var logo:UIImage = UIImage(named: "sgLogo")! --> EXC_BAD_ACCESS
var sgLogo:UIImageView = UIImageView(image: logo)
// other UI elements, + constraints
[...]
}
The only element I get is a stack trace, the debugger view in the bar below Xcode is empty. According to that stack trace, the UIImage seems to be instantiated: presence of a memory address.
The sgLogo image is a png image located in the project folder structure not in Images.xcassets. I tried to specify it in the images assets, but I'm still experimenting the same issue. Specifying the extension or not does not help either.
I can provide more code snippets if you want.
It seems that your image can not be found. Check the picture's target. For now you can fix the issue by removing the exclamation mark. If you force unwrap like this and the image is not there, your app will crash. So you can do something like this:
override func viewDidLoad() {
super.viewDidLoad()
var logo = UIImage(named: "sgLogo")
if let logo = logo {
let imgView = UIImageView(image: logo)
} else {
//image is nil
}
// other UI elements, + constraints
[...]
}
I succeeded to solve the issue. I was overriding the loadView method of my UIViewController, but not calling the parent method. Problem solved.