GPPSignInButton not loading the Google sign in image - ios

I have used GPPSignInButton in xib and then made a outlet connection . After even trying to set the image using the below code it does not set . Any solution on this would helpful
#IBOutlet var signInButton : GPPSignInButton?
override func viewDidLoad() {
super.viewDidLoad()
signInButton?.colorScheme = kGPPSignInButtonColorSchemeDark
signInButton?.style = kGPPSignInButtonStyleWide
signIn = GPPSignIn.sharedInstance()
signIn?.shouldFetchGoogleUserEmail = true
signIn?.clientID = GOOGLE_CLIENT_ID
signIn?.scopes = ["profile"]
signIn?.delegate = self
// signIn?.authenticate()
// signIn?.trySilentAuthentication()
}

I created a UIButton and set it Custom and then derived it from
GPPSignInButton in Custom class yet I do not have any luck
This is the problem.
When creating your xib, you /must/ use a UIView from the palette - not a UIButton.
If you drag in a UIButton, it will not work correctly.
Delete the button you added, drag in a "View", and set it's custom class to GPPSignInButton, re-connect your outlet, and you'll be fixed.
Do not use this one:
Do use this one:

Related

UiTextField inside UiStackView is not responding

Goal: I'm building a time sheet using swift ui.
Question: At the top I have class A that inherits from UiViewController. It lays out a UiStackView in a vertical stack to divide the screen into three: top,center,bottom. I'm having issues inside the center view. I can only get interaction with the UiTextField inside the center if I add it directly.
Inside the center view, I have a class B that inherits from UiView. Within the class I have another UiStackView that will add a horizontal stack to layout some items nicely.
I've made a class C in the same file outside of the center view class, and it inherits from UiView. It contains a UiTextField that I setup and add.
Here's where things get weird, I can do inside class B, and I will be able to work with the UiTextField just fine:
`let temp = ClassC (inherits UiView)
self.addSubView(temp)` <- works
`ClassBUiStackView.addSubView(ClassC)
UiView temp = UiView(...)
temp.addSubView(ClassBUiStackView)
self.addSubView(temp)` <- fails
Let me provide some actual code:
`class A: UiViewController{
override func viewDidLoad(){
super.viewDidLoad()
self.top = ...
self.cnr = Class B
self.btm = ...
self.ClassAUiStackView(arrangedSubviews: [top,cnr,btm])
...constraints...
self.view.addSubview(ClassAUiStackView)
}
}
class B: UiView{
override init(...){
super.init(...)
self.ClassBUiStackView(...x,y,width,heigh...)
...constraints...
let temp = UiView(...)
self.ClassBUiStackView.addSubView(ClassC)
temp.addSubView(ClassBUiStackView)
}
}
class C: UiView{
var UiTF: UiTextField!
required init(..., classB, ...){
...setup UiTf...
self.UiTF.addTarget(self, action: #selector(uitfAction), for: .allEvents)
self.addSubView(UiTf)
}
#objc func uitfAction(senderL UITextField!){
...some action...
}
}
`
Any help on this would be much appreciated. This is my first Swift app so I'm still a newbie. Please elaborate as much, I will read it all (multiple-times). Thank you !
i found the answer that will make all my ui components responsive again, i had to add uiStackView.translatesAutoresizingMaskIntoConstraints = true, if this is taken away or set to false, the ui components do not respond.

Round button on custom class with UIAppearance

I am trying to apply styles on a custom class using UIAppearance()
class MainStyleButton: UIButton {}
with a code:
let buttonView = MainStyleButton.appearance()
buttonView.backgroundColor = Style.buttonColor
buttonView.layer.cornerRadius = 5
buttonView.layer.borderWidth = 5
buttonView.layer.borderColor = Style.buttonColor.cgColor
It works with color, but unfortunately doesn't make my button round. I would appreciate any tips.
Tested on simulator iPhone X, 8 with iOS 11.2.
I tried replicating your approach and set up a button. I tried to change the button's appearance in a UIViewController during viewDidLoad and also in the AppDelegate during applicationDidFinishLaunching using your code. I additionally tested changing the button type to .custom from the default type .system. None of this seemed to work, I could not override the same attributes that you couldn't.
From Apple's docs I understand that the button type defines its appearance and also which appearance attributes can be overridden:
A button’s type defines its basic appearance and behavior. You specify the type of a button at creation time using the init(type:) method or in your storyboard file. After creating a button, you cannot change its type.
I do not know why the attributes of interest to you are not changeable at this point
However I would like to offer a different approach that I personally use and allows you to change the buttons appearance. Since you already defined your custom class it is much simpler to define corner radius and other attributes that you would like, like so (or you could write a style function with parameters that you can call at any time, to be able to change the appearance based on where the button is used):
class MainStyleButton: UIButton {
override func awakeFromNib() {
layer.borderColor = Style.buttonColor.cgColor
layer.borderWidth = 5
layer.cornerRadius = 5
}
}
Or you can instantiate/use an IBOutlet for a system button and do this:
class MyViewController: UIViewController {
#IBOutlet weak var myButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// not necessary to do this is viewDidLoad, that's just my example
myButton.layer.borderColor = Style.buttonColor.cgColor
myButton.layer.cornerRadius = 5
myButton.layer.borderWidth = 5
}

Load a nib file to act as a custom keyboard when a UITextField is tapped

I'm trying to load a .xib file to act as a custom keyboard when a textField is tapped. I'm able to show the .xib file (view) when the textField is tapped but I'm not sure how to communicate the buttons in the .xib file with the a textField in the ViewController.swift.
This is what I have done so far.
Created a single project.
Added a UITextField and created an outlet for it.
#IBOutlet weak var myField: MyTextField!
Created a new .xib file and called it CustomView.xib.
Created a new class and called it CustomView.swift.
Assigned class CustomView.swift to the CustomView.xib file.
Added some UIButtons in the CustomView.xib file. These will be acting as a custom-keyboard, they will show when the textField is tapped and hide when the resignFirstResponder method is called.
In the viewDidLoad method of the ViewController.swift I assigned inputView as follow.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var myField: MyTextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let myView = NSBundle.mainBundle().loadNibNamed("CustomView", owner: self, options: nil).first as? CustomView
myField.inputView = myView
}
}
Done
When I run the app and tap on the textField the .xib file shows (see picture below), my problem is, how do I communicate the buttons with the textField in the ViewController.swif. In other words what I want is to show the numbers in the inputField when they are tapped.
Any suggestions? Is this how this is usually done.
Here is an image that shows the view shown when the inputField was tapped.
Let's say you have 9 UIButtons, then consider ctrl + dragging an IBAction from all these buttons in storyboard to a single method such as:
- (IBAction)tapped:(id)sender
{
textView.text = [NSString stringWithFormat:#"%#%li", textView.text, (long)((UIButton*)sender).tag];
NSLog(#"%#", textView.text);
}
given that textField is your text field, you could then append each corresponding number from your keypad (that is to say, the buttons) using the tag property of these buttons and the aforementioned method.
You could set the tag number for each single button in storyboard (I.e., 1 - 9, respectively).
I didn't test it using 9 buttons but did with only 2, with tag numbers 1 and 2, respectively for each buttons. The result was displaying fine in UITextField (I.e., 1, 12, 122 and so forth).
Update (Post-comment):
I was able to re-create this using a nib file containing a few buttons and a UITextField in storyboard.
The process proceeds as follows:
1. Create a nib with all the buttons (which you already have done).
2. Create a view; and under "Custom Class", re-name the class to this view (I.e., "Custom Class" -> "Class" -> "view-that-holds-the-buttons").
3. Wire the IBActions (a total of 9 corresponding to the number of your buttons) to one single method as described above.
4. In your other view controller whose view hold the UITextField, load the nib using your existing method.
5. Add this view (from nib) as subview.
The following concerns with communication between the view (that holds the buttons along with the IBAction method) and the controller in which you load the nib:
6. create a delegate (weak) property.
7. Before you add the view (from nib), assign this delegate with the view controller (the control that loads the nib).
8. Create a protocol:
For instance:
protocol keypadProtocol : class
{
func displayKeys(keystrokeObject: AnyObject)
}
Have the view controller that loads the nib conform to this protocol and implement the required method (displayKeys):
//The one that loads the nib, which also holds the UITextField
class mainViewController: UIViewController, keypadProtocol
So, once the buttons are tapped, the IBAction would be called; but instead of displaying it, we send the sender to our delegate, which is the view controller that implements the displayKeys method and holds the UITextField.
The IBAction would be implemented as follows:
#IBAction func tapped(sender: AnyObject)
{
delegate!.displayKeys(sender)
}
displayKeys would be implemented like the following:
func displayKeys(keystrokeObject: AnyObject)
{
textView.text = NSString(format: "%#%li", textView.text! ?? "", (keystrokeObject as! UIButton).tag) as String
}
Declaration of the delegate in the controller where you load the nib file:
weak var delegate : keypadProtocol?
Assigning the delegate from within the view controller where you load the nib:
keyPadView.delegate = self //keyPadView is the nib file loaded
In reply to your second comment:
Assumption:
We have 2 classes.
The first one is a subclass of UIView, which is the xib, that holds the buttons.
Let’s call this „KeypadView“.
The second one is the main view controller, which is associated to the controller that holds
the UITextField in your storyboard.
Let’s call this „MainViewController“.
Step 2:
Firstly, please create a new UIView and name it, for the sake of consistency, „KeypadView“.
Then, click on your .xib file; on the right panel, click on the third tab from the left, which is called „Identity Inspector“; you would see „Custom Class -> Class“, where you would associate this xib to the class you created (you need this class, in order to connect the IBAction for the buttons from the xib file to it). It would be the „KeypadView“, which is a subclass of UIView.
Step 6:
You declare this in the class („KeypadView“) that holds the buttons.
Step 8:
You connect this method (IBAction) to the aforementioned class (I.e., „KeypadView“).
Once you load the xib („KeypadView“) from within the „mainViewController“, set the delegate in „KeypadView“ to self (self is the „MainViewController“):
let keyPadView = NSBundle.mainBundle().loadNibNamed("CustomView", owner: self, options: nil).first as? KeyPadView
keyPadView.delegate = self
self.view.addSubview(keypadView)
//you may need to re-adjust the position of the views; I will leave that to you
In your „KeyPadView“ class, there should be an IBAction that gets called from each of the buttons:
I.e.,
#IBAction func tapped(sender: AnyObject)
{
delegate!.displayKeys(sender)
}
Our delegate is the „mainViewController“, if you recall.
Since displayKeys is implemented in „mainViewController“, the following method would be called therein:
func displayKeys(keystrokeObject: AnyObject)
{
textView.text = NSString(format: "%#%li", textView.text! ?? "", (keystrokeObject as! UIButton).tag) as String
}
„mainViewController“ would then display the keystrokes in its UITextField (I.e., textView).

Use buttons inside subview

I'm making a multiple choice quiz game, and my goal right now is to have four buttons that refresh by spinning around with new answer choices. I think that means I need a subview that animates and re-populates with new buttons--if that's incorrect or not best, please stop me here.
At any rate, I created the subview in my storyboard, put the buttons inside it (background is blue just to see it now):
I dragged that over to my ViewController to make an IBOutlet (buttonContainer) and added this code to my ViewDidLoad:
view.addSubview(buttonContainer)
let buttonTap = UITapGestureRecognizer(target:self, action: Selector("checkAnswer"))
buttonTap.numberOfTapsRequired = 1
buttonContainer.addGestureRecognizer(buttonTap)
buttonContainer.userInteractionEnabled = true
However: When I run it in the simulator, the blue background does not appear at all, but the buttons are still disabled.
Before creating the subview, both the buttons and the function (checkAnswer) they called all worked perfectly.
You don't need any of this code if you are creating everything in storyboard. Just create a new class for the containerview and connect the buttons as an outlet collection.
For example, your button container class might look something like this:
class ButtonContainerView: UIView {
#IBOutlet var answerButtons: [UIButton]!
func rotateButtons() {
for button in answerButtons {
var context = UIGraphicsGetCurrentContext()
UIView.beginAnimations(nil, context: &context)
UIView.setAnimationCurve(UIViewAnimationCurve.Linear)
UIView.setAnimationDuration(5.0)
button.transform = CGAffineTransformRotate(button.transform, CGFloat(M_PI))
UIView.commitAnimations()
}
}
}

iOS using xib + global methods for overlay UIView (Swift)

I'm writing an app that should present overlays in specific situations, like for example the lack of location services enabled for the app.
Overlay is a UIView with a UIImageView (background) a UILabel (title) and a UIButton calling a specific action. I want to use Interface Builder to set up the overlay UI but I would like to recall the overlay and show it on different UIViewControllers, depending on when the lack of location services is detected.
I have set up a custom class (subclass of UIView) to link a xib file. Code below:
class LaunchCustomScreen: UIView
{
#IBOutlet var title: UILabel!
#IBOutlet var enableLocationButton: UIButton!
#IBOutlet var waitingIndicator: UIActivityIndicatorView!
#IBOutlet var bckgroundImage: UIImageView!
func setupDefault()
{
title.text = "Location Services Required"
enableLocationButton.setTitle("Enable Location Services", forState: UIControlState.Normal)
enableLocationButton.addTarget(self,
action: "promptUserForLocation",
forControlEvents: UIControlEvents.TouchUpInside)
hideLocButton()
}
func hideLocButton()
{
enableLocationButton.hidden = true
}
func showLocButton()
{
enableLocationButton.hidden = false
}
}
Then I have created the xib file which is of Class LaunchCustomScreen and I linked the IBOutlets to all the objects in it (UILabels, UIBUtton, UIImageView)
Then I have set some global functions to be called from any other UIViewController in order to show/hide the overlay on the specific view controller and configure it with UIButton hidden or visible (it will be hidden with a waiting indicator when user location is still loading). Below related code:
func setupLaunchDefault(vc: UIViewController) -> LaunchCustomScreen
{
for aSubview in vc.view.subviews
{
if aSubview.isKindOfClass(LaunchCustomScreen)
{
NSLog("Found already a launch screen. Removing")
aSubview.removeFromSuperview()
}
}
var screen: LaunchCustomScreen = LaunchCustomScreen()
screen.setupDefault()
return screen
}
func showLaunchAskLocation(vc:UIViewController)
{
var screen = setupLaunchDefault(vc)
screen.bounds = vc.view.bounds
screen.showLocButton()
vc.view.addSubview(screen)
}
Now I'm trying if the solution works and it crashes on the setupLaunchDefault function. Reason is that even if an instance of LaunchCustomSCreen is created, the variables (title, enableLocationButton) are still nil. I though they should be non-nil thanks to the IBOutlet to the xib... what am I missing?
Thank you in advance for your help!
I have set up a custom class (subclass of UIView) to link a xib file
No, you haven't. No such "link" is possible.
what am I missing?
You're not missing anything, because you've already figured it out!
Merely creating a LaunchCustomScreen instance out of thin air (i.e. by saying LaunchCustomScreen(), as you are doing) merely creates an instance of this class. It has nothing whatever to do with the .xib (nib) file! There is no magic "link" whatever between the class and the nib! Thus, nothing happens that would cause these properties to get any value. They are, as you have rightly explained, nil.
You have designed and configured one special particular instance of LaunchCustomScreen in the nib. That is the instance whose outlets are hooked up, within the same nib. So if you want an instance of LaunchCustomScreen with hooked-up outlets, you must load the nib! Loading the nib is exactly equivalent to making an instance of what's in the nib - it is a form of instantiation. And here, it's the form of instantiation you want, because this instance is the instance you want.
So, the answer is: do not say LaunchCustomScreen() to get your LaunchCustomScreen instance (screen). Instead, load the nib to get your LaunchCustomScreen instance - and all will be well.
So, let's say your .xib file is called LaunchCustomScreen.xib. You would say:
let arr = NSBundle.mainBundle().loadNibNamed("LaunchCustomScreen", owner: nil, options: nil)
let screen = arr[0] as UIView
The first result, arr, is an array of top-level objects instantiated from the nib. The first of those objects (probably the only member of the array) is the view you are after! So you cast it to a UIView and you are ready to stick it into your interface. Since the view comes from the nib, its outlets are set, which is what you're after. You can do this as many times as you need to, to get as many "copies" of this view as you like.

Resources