Method name gets changed in storyboard connections inspector - ios

I created a method for a button using Swift 2.3 in Xcode 8. let's say
#IBAction func testAction(sender: UIButton) {
print("\(sender.tag)");
}
but in Connections inspector of storyboard editor it shows as testActionWithSender:, which I know is not the correct method name but I have no problem with that until it crashes with
[TestProject.ViewController testActionWithSender:]: unrecognized selector sent to instance 0x7ff3f3e050e0
on button tap.
So why does the method name changes in Connections inspector and how do I fix it?

By Using this workaround you can add existing action and also can connect multiple buttons to a single action.
I think there is a bug in Xcode8. You can add multiple/Single button to a single action /function by changing sender to _ sender
eg :- Normal Button
#IBAction func huu(sender: UIButton) {
}
You can't add multiple buttons or single button to this action you need to simply change like this and then you can add multiple buttons by using drag and connect from storyboard.
#IBAction func huu(_ sender: UIButton) {
}
After connecting IBOutlets Xcode will show a warning like this :-
To remove this warning simple delete _ sign from the action/function. Make sure that to delete _ after connecting your IBOutlets
Hope that this will gonna help you! :)

I faced the same issue. The only workaround I found is to delete the connection, and drag the button action to a new Action method.
If you link your button to an existing one, it crashes

Related

How to add parameters to an #objc function in Swift 4 when creating an application programatically?

I have always found my answers in previous posts, though not found any answer to this question yet.
After creating multiple applications with help of the storyboard, I am now making my first application with code only.
My problem, I am just trying to make a simple function (create user in Firebase and execute segue to next screen) that will be executed after a button has been pressed.
I can create a function that triggers the segue, though for some reason it seems impossible to create the user (Firebase function, needing users input from textFields) in the same function. In the below defined function I cannot use the current user input of textFields that I defined programatically in the ViewDidLoad function, nor can I create parameters in my #objc function.
#objc func registerPressed(email: String, password: String) {
performSegue(withIdentifier: "MainVC", sender: nil)
}
What can I do? Is there a way to create parameters in the function above? Is there an easier/better way than using addTarget? Can I somehow use an #IBAction call? Should I define my textFields before the ViewDidLoad function?
No , you can't do this
#objc func registerPressed(email: String, password: String) {
for a button target selector , as the only paramter that's passed is
#objc func registerPressed(_ sender:UIButton) {
and it's logical as from where do you think the button will get those parameters for you , so you have to create the outlets for the textfields and validate them befoe sending to firebase
BTW there is no difference between creating addTarget method for the button or linking it with #IBAction
There is a perfectly standard pattern. The email and password info must already exist in instance properties. You trigger the segue and prepare(for:) will be called; it picks up the info from the properties and passes them into the destination view controller.

Swift: Edit value of Label when pressing a button

I'm trying to learn Swift and I'm playing around with the basics of variables. I made an app where when you press a button, the value of a label changes, and while the button that adds 1 works, the one that subtracts one doesn't. If I change the first button (plusone) to subtract one, then it works, so I assume it is something to do with how the code is parsed? Would you be kind enough to explain how this works? Thanks in advance.
The code is here:
import UIKit
class ViewController: UIViewController {
var value = 0
#IBOutlet var number: UILabel!
#IBAction func plusone(_ sender: Any) {
value = value+1
number.text = "\(value)"
}
#IBAction func plustwo(_ sender: Any) {
value = value-1
number.text = "\(value)"
}
}
And the app looks like this if that matters:
Screenshot
The second button is named 'plustwo' because I haven't figured out where else I need to rename it, if I just rename it here the app displays a blank screen and nothing else.
From the comments:
I changed plustwo to -2 and it works as intended. Pressing Add One
adds one and pressing Substract One substracts one. I am not sure why.
The behavior you describe tells me that you have your Subtract One button wired to both the plusone and plustwo functions. You can check this by control-clicking on your button in Interface Builder and checking the connections. If you see TouchUpInside wired to two functions, remove one by clicking on the x to delete the connection.
Another way you can verify the behavior is to add logging print statements to your functions such as print("in plusone") and print("in plustwo"). When you press Subtract One, if you see both messages in the console then you know you have your button connected to both #IBActions.
How did this happen? This frequently happens when you copy a button in Interface Builder that already has a connection to an #IBAction. Connecting it to a new #IBAction doesn't replace the first one, it just connects to both of them and calls both when the button is pressed.
The second button is named 'plustwo' because I haven't figured out
where else I need to rename it, if I just rename it here the app
displays a blank screen and nothing else.
To rename the function, you need to change the name of the function and remove and reconnect the connection in Interface Builder. As described above, control-click on the button in Interface Builder and remove the connection to the old function name, then connect the button to the new function.

Can't change custom class of UIButton to GIDSignInButton

I'm trying to add Google sign in functionality to a custom button, and I'm following this tutorial. It's telling me to select the button, and set its class as GIDSignInButton, then add this code: #IBOutlet weak var signInButton: GIDSignInButton!.
However, it doesn't let me set the class to GIDSignInButton. When I type it in and press enter, the field just clears.
You should try assign GIDSignInButton not to the Button Object from the Object library but to the the View Object instead
It's work for me.
It will look like this using UIView instead of UIButton.
You can create UIButton and then on its action method you can write this code for signing via google:
GIDSignIn.sharedInstance().signIn()
It works for me, in this way you can customize UIButton according to your requirement and also perform signin by using google
That's because GIDSignInButton is a subclass of UIView, not UIButton.
Add to the storyboard / nib a regular UIView and change it's class to GIDSignInButton instead.
From google doc:
Add a GIDSignInButton to your storyboard, XIB file, or instantiate it
programmatically. To add the button to your storyboard or XIB file,
add a View and set its custom class to GIDSignInButton.
GIDSignInButton can be set by using a UIView or a UIButton.
If you are using GIDSignInButton as a UIButton
open the storyboard as source code
Find the button in resulting XML
Add the below code as an attribute for the button tag
customClass="GIDSignInButton"
4.open storyboard again as Interface Builder, button class will be changed
If you are using GIDSignInButton as a UIView
1.copy paste the custom class as GIDSignInButton in Identity Inspector
The second one is the correct approach in my opinion.
The workaround is open the storyboard in text mode and put it directly. When you return to the interface builder it will show normally.
Open storyboard as source code.
Locate the button in the xml.
Set customClass="GIDSignInButton" as an attribute for the button tag.
Open storyboard as interface builder.
You can now link the button to the IBOutlet
If you use a UIView instead of a UIButton, you can assign the view a custom class of GIDSignInButton. From there you can connect the view to a button outlet and action as seen below.
#IBOutlet weak var googleLoginButton: GIDSignInButton!
#IBAction func googleLoginButtonPressed(_ sender: Any) {
GIDSignIn.sharedInstance()?.signIn()
}
I had the same problem a few months ago,
Your code seems to be right
#IBOutlet weak var signInButton: GIDSignInButton!
But, the problem might be
• You haven’t added the Framework properly
(Go to your project setting in the left side navigator, and click Build phases, add your framework and SHIFT + CMD + K)
• Or alternatively, go ahead and write the #IBOutlet in your swift file, then drag the button to assign it
• your last option is to close xcode, or maybe delete the derived data
Xcode itself has plenty of bugs, I am not sure if it’s your problem, it’s xcode’s
Hope this helps!
The simple way to do is just make a button action and paste the following lines in it.
#IBAction func gSignInAction(_ sender: Any) {
GIDSignIn.sharedInstance()?.signIn()
}
Use UIView instead of UIButton and assign custom class as GIDSignInButton
Swift- 5
Open storyboard as source code.
Locate the button in the xml.
Set customClass="GIDSignInButton" as an attribute for the button tag.
Open storyboard as interface builder.
//MARK:- You will not find this with button XML Forcly Add this (customClass="GIDSignInButton")[![enter image description here][1]][1]

Swift error : signal SIGABRT how to solve it

I'm just a beginner in Swift coding. My idea is quite simple which is an app with two buttons. When clicked, a textfield will change its text.
In the Main.StoryBoard, I add a textfield and two buttons.
In ViewController.swift file. I write as this:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var textfield: UITextField!
#IBOutlet weak var button: UIButton!
#IBOutlet weak var button2: UIButton!
#IBAction func action1(_ sender: UIButton) {
textfield.text="you just clicked on button1"
}
#IBAction func action2(_ sender: UIButton) {
textfield.text="you just clicked on button2"
}
}
It is supposed to be all right. However, an error appears which shows:
thread1:signal SIGABRT
in file AppDelegate.swift line:
class AppDelegate: UIResponder, UIApplicationDelegate
What is wrong with my code?
You get a SIGABRT error whenever you have a disconnected outlet. Click on your view controller in the storyboard and go to connections in the side panel (the arrow symbol). See if you have an extra outlet there, a duplicate, or an extra one that's not connected. If it's not that then maybe you haven't connected your outlets to your code correctly.
Just remember that SIGABRT happens when you are trying to call an outlet (button, view, textfield, etc) that isn't there.
For me it wasn't an outlet. I solved the problem by going to the error And reading what it said. (Also Noob..)
This was the error:
And The solution was here:
Just scroll up in the output and the error will be revealed.
To solve the problem, first clean the project and then rebuild.
To clean the project, go to MenuBar: Product -> Clean
Then to rebuild the project, just click the Run button as usual.
A common reason for this type of error is that you might have changed the name of your IBOutlet or IBAction you can simply check this by going to source code.
Click on the main.storyboard and then select open as
and then select source code
source code will open
and then check whether there is the name of the iboutlet or ibaction that you have changed , if there is then select the part and delete it and then again create iboutlet or ibaction.
This should resolve your problem
In my case I wasn't getting error just the crash in the AppDelegate and I had to uncheck the next option: OS_ACTIVITY_MODE then I could get the real crash reason in my .xib file
Hope this can help you too :)
I had the same problem. I made a button in the storyboard and connected it to the ViewController, and then later on deleted the button. So the connection was still there, but the button was not, and so I got the same error as you.
To Fix:
Go to the connection inspector (the arrow in the top right corner, in your storyboard), and delete any unused connections.
If you run into this in Xcode 10 you will have to clean before build. Or, switch to the legacy build system. File -> Workspace Settings... -> Build System: Legacy Build System.
This is a very common error and can happen for multiple reasons. The most common is when an IBOUTLET/IBACTION connected to a view controller in the storyboard is deleted from the swift file but not from the storyboard. If this is not the case, use the log in the bottom toolbar to find out what the error is and diagnose it. You can use breakpoints and debugging to aid you in finding the error.
To find out how to fix the error please use this article that I found on Google: https://rayaans.com/fixing-the-notorious-sigabrt-error-in-xcode
In my case there was no log whatsoever.
My mistake was to push a view controller in a navigation stack that was already part of the navigation stack.
Sometimes it also happens when the function need to be executed in main thread only, so you can fix it by assigning it to the main thread as follows :-
DispatchQueue.main.async{
your code here
}
For me, This error was because i had a prepare segue step that wasn't applicable to the segue that was being done.
long story:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
let gosetup = segue.destination as! Update
gosetup.wherefrom = updatestring
}
This was being done to all segue when it was only for one. So i create a boolean and placed the gosetup inside it.
In my case, I was using RxSwift for performing search.
I had extensively kept using a shared instance of a particular class inside the onNext method, which probably made it inaccessible (Mutex).
Make sure that such instances are handled carefully only when absolutely necessary.
In my case, I made use of a couple of variables beforehand to safely (and sequentially) store the return values of the shared instance's methods, and reused them inside onNext block.
I had the same problem. In my case I just overwrote the file
GoogleService-Info.plist
on that path:
Platform\ios\YOUR_APP_NAME\Resources\Resources
In my case the files were present without data.
If this crash occurs when accessing a view controller within a package you may have to remove the Class and Storyboard ID from the view controller within the package and then add them again, run the project and the view controller should be found

Having issues with nib from ios_google_places_autocomplete

Thank you for viewing this page.
I have downloaded the following from GH: https://github.com/watsonbox/ios_google_places_autocomplete
It uses a nib file to initiate a autocomplete feature within a ViewController (in the Main Storyboard.
Issues
The following issues are hindering my progress;
I am unable to close the nib view using the X (or Stop button). The
nib loads via ViewDidLoad, therefore every time it dismisses itself,
it will be shown again. I have attempted to do the following but it
does not work.
When any cell is selected, I am unable to go back to the ViewController I originally navigated from. (same as point 1,
however should happen once I select any of the cells).
extension LocoSearch: GooglePlacesAutocompleteDelegate {
func placeSelected(place: Place) {
println(place.description)
println(place.id)
var locoResult = PFUser.currentUser()
locoResult["placeDesc"] = place.description
locoResult["placeId"] = place.id
locoResult.pin()
self.performSegueWithIdentifier("locoDone", sender: self)
}
func placeViewClosed() {
dismissViewControllerAnimated(true, completion: {
self.performSegueWithIdentifier("locoDone", sender: self)
})
To stop the autocomplete controller from loading every time the view loads, either remove it from viewDidLoad (and put it in a button click handler, for example), or if that's really where it belongs then perhaps use a variable stored property to store the currently selected Place and only show the autocomplete controller if none exists.
placeSelected is the correct callback for handling selections. Perhaps you should dismiss the autocomplete view before performing the segue as you do in your close handler? Please link a Github project with this issue if you really can't get it working.

Resources