Making Payments using Square SDK Swift 3 - ios

As I'm trying to make payments using Square SDK from Github (https://github.com/square/SquareRegisterSDK-iOS) I'm not able to find the amount in Square POS App which i have passed from my App.
Please find the below steps which i have actually followed.
I have downloaded Square Register SDK from below git hub link.
https://github.com/square/SquareRegisterSDK-iOS
I Ran the application using cocoa pods and i have successfully installed the pod file in my project.
I have created a test App in my Client login in My Apps Section .
App Name : MyApp
App Id: XXXXXXXXXXXXXX (My Application Id From Square Dashboard)
I have Registered My Bundle Id And Callback Url in Register Api Section
iOS App Bundle IDs: My Bundle Id
iOS App URL Schemes: my Call Back Url
As my account is Activated for Receiving payments through applications.
Now coming back to my code, i just took Square Register SDK ----> SwiftCharge class methods as it is.
Please find the below code what i have used for charge and please do let me know any corrections to be done from my end.
import SquareRegisterSDK
import UIKit
let yourClientID = "xxxxxxxxxx"
let yourCallbackURL = URL(string: "MyApp://callback")!
enum Section: Int {
case amount = 0, supportedTenderTypes, optionalFields, settings
init?(at indexPath: IndexPath) {
self.init(rawValue: indexPath.section)
}
}
let allTenderTypes: [SCCAPIRequestTenderTypes] = [.card, .cash, .other, .squareGiftCard, .cardOnFile]
extension String {
var nilIfEmpty: String? {
return isEmpty ? nil : self
}
}
class ViewController: UIViewController {
var supportedTenderTypes: SCCAPIRequestTenderTypes = .card
var clearsDefaultFees = false
var returnAutomaticallyAfterPayment = true
#IBOutlet weak var currencyField: UITextField!
#IBOutlet weak var amountField: UITextField!
#IBOutlet weak var notesField: UITextField!
#IBOutlet weak var userInfoStringField: UITextField!
#IBOutlet weak var merchantIDField: UITextField!
#IBOutlet weak var customerIDField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func awakeFromNib() {
super.awakeFromNib()
// Always set the client ID before creating your first API request.
SCCAPIRequest.setClientID(yourClientID)
}
#IBAction func charge(sender: AnyObject) {
let currencyCodeString = "USD"
let amountString = "500"
let amount: SCCMoney
guard let amountCents = Int(amountString) else {
showErrorMessage(title: "Invalid Amount", message: "\(amountString) is not a valid amount.")
return
}
do {
amount = try SCCMoney(amountCents: amountCents, currencyCode: currencyCodeString)
} catch let error as NSError {
showErrorMessage(title: "Invalid Amount", error: error)
return
}
let userInfoString = "Radhachandan"
let merchantID = ""
let customerID = ""
let notes = "Sample Test"
let request: SCCAPIRequest
do {
request = try SCCAPIRequest(callbackURL: yourCallbackURL,
amount: amount,
userInfoString: userInfoString,
merchantID: merchantID,
notes: notes,
customerID: customerID,
supportedTenderTypes: supportedTenderTypes,
clearsDefaultFees: clearsDefaultFees,
returnAutomaticallyAfterPayment: returnAutomaticallyAfterPayment)
} catch let error as NSError {
showErrorMessage(title: "Invalid Amount", error: error)
return
}
do {
try SCCAPIConnection.perform(request)
} catch let error as NSError {
showErrorMessage(title: "Cannot Perform Request", error: error)
return
}
}
private func showErrorMessage(title: String, error: NSError) {
showErrorMessage(title: title, message: error.localizedDescription)
}
private func showErrorMessage(title: String, message: String) {
let alertView = UIAlertController(title: title, message: message, preferredStyle: .alert)
alertView.addAction(UIAlertAction(title: "Dismiss", style: .default, handler: nil))
present(alertView, animated: true, completion: nil)
}
}
As of now It was redirect to Square Point Of Sale app, but its not displaying the amount what i have passed.
Your kind feedback will be greatly appreciated.

Try modifying your code like this:
...
let userInfoString = "Radhachandan"
let merchantID = nil
let customerID = nil
let notes = "Sample Test"
...
You have alerted us of a bug when passing empty strings for these parameters, we will be working on the fix soon.

Related

Passcode with TouchiD Error "Type is ambiguous without more context"

I am using some code off of github and trying to convert it to Swift 3.0. I have done everything up until now, but I am getting this one error on 3 lines in the code:
Type of expression is ambiguous without more context
Below I have marked the lines that are labeled by this error. How do I go about fixing this? Everything else works that I know of. I just can't test the demo itself until this is fixed.
//
// PasscodeSettingsViewController.swift
// PasscodeLockDemo
//
// Created by Yanko Dimitrov on 8/29/15.
// Copyright © 2015 Yanko Dimitrov. All rights reserved.
//
import UIKit
import PasscodeLock
class PasscodeSettingsViewController: UIViewController {
#IBOutlet weak var passcodeSwitch: UISwitch!
#IBOutlet weak var changePasscodeButton: UIButton!
#IBOutlet weak var testTextField: UITextField!
#IBOutlet weak var testActivityButton: UIButton!
fileprivate let configuration: PasscodeLockConfigurationType
init(configuration: PasscodeLockConfigurationType) {
self.configuration = configuration
super.init(nibName: nil, bundle: nil)
}
#IBAction func passcodeSwitchValueChange(_ sender: UISwitch) {
let passcodeVC: PasscodeLockViewController
if passcodeSwitch.isOn {
// Error on next line
passcodeVC = PasscodeLockViewController(state: .SetPasscode, configuration: configuration)
} else {
// Error on next line
passcodeVC = PasscodeLockViewController(state: .RemovePasscode, configuration: configuration)
passcodeVC.successCallback = { lock in
lock.repository.deletePasscode()
}
}
present(passcodeVC, animated: true, completion: nil)
}
#IBAction func changePasscodeButtonTap(_ sender: UIButton) {
let repo = UserDefaultsPasscodeRepository()
let config = PasscodeLockConfiguration(repository: repo)
let passcodeLock = PasscodeLockViewController(state: .ChangePasscode, configuration: config)
// Error on next line
presentViewController(passcodeLock, animated: true, completion: nil)
}
}
The master branch of the repo contains previous version of Swift. After automatic conversion (when you first clone the project and open with Xcode and Xcode prompts you to convert to Current Swift Syntax) the LockState enum inside PasscodeLockViewController class becomes:
public enum LockState {
case enterPasscode
case setPasscode
case changePasscode
case removePasscode
func getState() -> PasscodeLockStateType {
switch self {
case .enterPasscode: return EnterPasscodeState()
case .setPasscode: return SetPasscodeState()
case .changePasscode: return ChangePasscodeState()
case .removePasscode: return EnterPasscodeState(allowCancellation: true)
}
}
}
In the demo project where you are instantiating you are using: (Here the enumeration case is Uppercased as .SetPasscode)
passcodeVC = PasscodeLockViewController(state: .SetPasscode, configuration: configuration)
You have to change this initialization to:
passcodeVC = PasscodeLockViewController(state: .setPasscode, configuration: configuration)
And for other recurring same type error in Xcode, you have to change them respectively.

Referencing IBOutlet in another View Controller

So, I have been having some major trouble figuring this out and I have searched extensively for a solution but I surprisingly could not find one. I am attempting to create a multiple page (5, to be exact) Sign-Up for users.
I'll start off by showing you the layout of page 1 and 5 (since solving that issue will solve the issue for page 2-4):
Sign Up Page #1
Sign Up Page #5
As you may see (from the page control dots), I am using a page view controller to allow users to scroll from page to page. What I am trying to accomplish is giving the user the ability to enter their sign-up information in pages 1-5 before submitting it all at once (which can be located on page 5).
Here is the current code I am using for page #1:
class SignUpInfoViewController: UIViewController {
#IBOutlet weak var emailTextField: UITextField!
#IBOutlet weak var passwordTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Here is the current code I am using for page #5:
class TermsOfUseViewController: UIViewController {
let minPasswordCharCount = 6
#IBAction func signUpAction(_ sender: Any) {
let providedEmailAddress = SignUpInfoViewController().emailTextField.text!
let providedPassword = SignUpInfoViewController().passwordTextField.text!
let trimmedPassword = providedPassword.trimmingCharacters(in: CharacterSet.whitespacesAndNewlines)
if !(validEmail(enteredEmail: providedEmailAddress) && validPassword(enteredPassword: trimmedPassword)) {
invalidCredentialsAlert()
}
else {
FIRAuth.auth()?.createUser(withEmail: providedEmailAddress, password: providedPassword) { user, error in
if error == nil {
FIRAuth.auth()!.signIn(withEmail: providedEmailAddress,
password: providedPassword)
}
else {
let alertController = UIAlertController(title: "Error", message: error?.localizedDescription, preferredStyle: .alert)
let defaultAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
alertController.addAction(defaultAction)
self.present(alertController, animated: true, completion: nil)
}
}
}
}
// Email is valid if it has a standard email format
func validEmail(enteredEmail: String) -> Bool {
let emailFormat = "[A-Z0-9a-z._%+-]+#[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailPredicate = NSPredicate(format:"SELF MATCHES %#", emailFormat)
return emailPredicate.evaluate(with: enteredEmail)
}
// Password is valid if it is not empty or greater than a specified number of characters
func validPassword(enteredPassword: String) -> Bool {
if (enteredPassword != "" && enteredPassword.characters.count >= minPasswordCharCount) {
return true
}
return false
}
In the TermsOfUseViewController class, I am attempting to use the emailTextField and passwordTextField outlets from the SignUpInfoViewController, but I am receiving the following error:
fatal error: unexpectedly found nil while unwrapping an Optional value
I debugged the error and saw that the emailTextField property from SignUpInfoViewController is nil and so force unwrapping it will cause the app to crash (Note: I have correctly connected the IBOutlets to the SignUpInfoViewController, so no issue there).
How can I safely transfer the usage of the IBOutlets from the SignUpInfoViewController class to the TermsOfUseViewController class without it crashing? In other words, how can I make it to where the IBOutlets are no longer nil when I reference them in the TermsOfUseViewController class?
Thank you!
That is a perfect scenario for delegate pattern
protocol SignUpProtocol: class {
func didProvideUserData(username: String ,password: String)
}
In your signup class declare a delegate: public weak var delegate:SignUpProtocol?
I am assuming when the user has provided the require info, they need to press some button to go to the next step: Thus in that button you should raise the delegate
#IBAction func nextButton(sender:UIButton) {
guard let username = usernameTextfield?.text, let password = passwordTextField?.text, else { fatalError("textfields were empty") }
if delegate != nil { // this saying when someone is listening to me, I will expose any method associated to me
delegate?.didProvideUserData(username:username, password:password) // passing the username and password from textfield
}
}
if you don't have a button, then look at property observer, where you could have some property
var didFulfill:Bool? = nil {
didSet {
if didFulfill != nil && didFulfill == true {}
// here you check if your textfields are sets then raise the delegate
}
}
set this property didFulfill = when both textfields are not empty :)
Now in your Terms class, just subscribe to that delegate
class TermsOfUseViewController: UIViewController, SignUpProtocol {
var signUpVc: SignUpInfoViewController?
override func viewDidLoad() {
super.viewDidLoad()
signUpVc = SignUpInfoViewController()
signUpVc?.delegate = self
}
func didProvideUserData(username: String, password:String) {
// there is your data
}
}
You have to take in account that you don't have all references for all UIPageViewControllers all the time. That being said, I would suggest either to keep object in UIPageViewController with updated information or using Singleton Pattern to use it to store info into it and later use it. UIPageViewController are being reused and you might have one before and one after and relying onto having them would be wrong.
You can use UIPageViewController as self.parentViewController or something like that.

How to find child name from a value [duplicate]

This question already has an answer here:
How to fetch email id from JSON file in firebase using swift
(1 answer)
Closed 6 years ago.
I need your help. I am developing an IOS app using firebase and swift. I have a list of users in JSON file, using that JSON file I am trying to authenticate user.
At the moment, my code can retrieve value of email. My goal is to get the ID if I give my Input as email. For examlple: IF i give email as sandeep#gmail.com then I need it ID as 231. For this I have written a function findParent(), but i am getting this error "cannot convert value of type 'UITextfield' to expected argument type 'string'". Please help me.
Below are supplements:
Json File:
[
{
"ID": 231,
"iN_Hub Membership": 12345,
"title": "Mr.",
"firstname": "kumar",
"lastname": "sandeep",
"email": "sandeep#gmail.com",
},
Swift code:
import UIKit
import Firebase
import FirebaseAuth
//import FirebaseDatabase
class ViewController: UIViewController {
#IBOutlet weak var emailofUser: UITextField!
#IBOutlet weak var passwordofUser: UITextField!
var ref:FIRDatabaseReference! //created a variable ref of type firebase database reference
var databaseHandle:FIRDatabaseHandle? //to handle to database listener like to stop or start it
override func viewDidLoad() {
super.viewDidLoad()
ref = FIRDatabase.database().reference()
let newRef = ref.child("4")
newRef.queryOrderedByKey().observeEventType(.Value, withBlock: { snapshot in
let userId = snapshot.value!["ID"]
let memberhipNum = snapshot.value!["iN_Hub Membership"]
let emailID = snapshot.value!["email"]
print(userId)
print(memberhipNum)
print(emailID)
})
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func LoginPage(sender: UIButton) {
func findParent(emailid: String) {
//set firebase reference
ref = FIRDatabase.database().reference()
ref.child(emailid ).queryOrderedByKey().observeEventType(.Value, withBlock: { snapshot1 in
let myuserID = snapshot1.value!["ID"]
print(myuserID)
})
}
findParent(emailofUser)
if let email = emailofUser.text, pass = passwordofUser.text {
FIRAuth.auth()?.signInWithEmail(email, password: pass, completion: { (user, error) -> Void in
if error == nil{
print("Now its working. Well done Sandeep!!")
self.performSegueWithIdentifier("UserDetails", sender: self)
}
else{
print("nonononono")
let alertController = UIAlertController(title: "oops!", message: "user name and password combination is wrong!", preferredStyle: .Alert)
let defaultAction = UIAlertAction(title: "Ok", style: .Cancel, handler: nil)
alertController.addAction(defaultAction)
self.presentViewController(alertController, animated: true, completion: nil)
}
})
}
}
}
Hope anyone will help me. Thank you in advance.
One mistake that could be the problem:
findParent(emailofUser)
Should be:
findParent(emailofUser.text)

Errors while implementing Chromecast in swift 3

I seem to have a problem implementing ChromeCast features in a project of mine.
I have been trying to implement the GCKDeviceScannerListener Singleton Class on a UIViewController, however its delegate methods are not getting called.
The deviceDidComeOnline method of GCKDeviceScannerListener never gets called.
Instead I have a bunch of error displayed by the chromeCast logger as followed:
+[NSMutableDictionary(GCKAdditions) gck_loadFromCacheWithName:] - Device cache file file:///Users/martin/Library/Developer/CoreSimulator/Devices/318D2E15-C4B0-47D2-97AF-CD560A6063AE/data/Containers/Data/Application/C117BB98-88DA-4586-B119-0683DAD82FEB/Library/Caches/gck_nearby_devices.plist doesn't exist.
+[NSMutableDictionary(GCKAdditions) gck_loadFromCacheWithName:] - Device cache file file:///Users/martin/Library/Developer/CoreSimulator/Devices/318D2E15-C4B0-47D2-97AF-CD560A6063AE/data/Containers/Data/Application/C117BB98-88DA-4586-B119-0683DAD82FEB/Library/Caches/gck_network_cache.plist doesn't exist.
scanning started
+[NSMutableDictionary(GCKAdditions) gck_deleteCacheWithName:] - Device cache file file:///Users/martin/Library/Developer/CoreSimulator/Devices/318D2E15-C4B0-47D2-97AF-CD560A6063AE/data/Containers/Data/Application/C117BB98-88DA-4586-B119-0683DAD82FEB/Library/Caches/gck_device_cache.plist doesn't exist.
+[NSMutableDictionary(GCKAdditions) gck_deleteCacheWithName:] - Device cache file file:///Users/martin/Library/Developer/CoreSimulator/Devices/318D2E15-C4B0-47D2-97AF-CD560A6063AE/data/Containers/Data/Application/C117BB98-88DA-4586-B119-0683DAD82FEB/Library/Caches/gck_device_cache_v1.plist doesn't exist.
+[NSMutableDictionary(GCKAdditions) gck_deleteCacheWithName:] - Device cache file file:///Users/martin/Library/Developer/CoreSimulator/Devices/318D2E15-C4B0-47D2-97AF-CD560A6063AE/data/Containers/Data/Application/C117BB98-88DA-4586-B119-0683DAD82FEB/Library/Caches/gck_device_cache_v2.plist doesn't exist.
+[NSMutableDictionary(GCKAdditions) gck_loadFromCacheWithName:] - Device cache file
file:///Users/martin/Library/Developer/CoreSimulator/Devices/318D2E15-C4B0-47D2-97AF-CD560A6063AE/data/Containers/Data/Application/C117BB98-88DA-4586-B119-0683DAD82FEB/Library/Caches/gck_device_cache_v3.plist doesn't exist
I can't seem to figure out why I have these errors. But it seems that the deviceScanner never even finds my receiver device.
My viewController code is:
class ChromeCastViewController: UIViewController, GCKDeviceScannerListener, GCKDeviceManagerDelegate, GCKMediaControlChannelDelegate{
fileprivate let kCancelTitle = "Cancel"
fileprivate let kDisconnectTitle:String! = "Disconnect"
// Publicly available receiver to demonstrate sending messages - replace this with your
// own custom app ID.
fileprivate let kReceiverAppID = "XXXXXXXXX"
fileprivate lazy var btnImage:UIImage = {
return UIImage(named: "icon-cast-identified.png")!
}()
fileprivate lazy var btnImageselected:UIImage = {
return UIImage(named: "icon-cast-connected.png")!
}()
fileprivate var deviceScanner:GCKDeviceScanner?
fileprivate var deviceManager:GCKDeviceManager?
fileprivate var mediaInformation:GCKMediaInformation?
fileprivate var selectedDevice:GCKDevice?
#IBOutlet weak var googleCastButton: UIBarButtonItem!
#IBOutlet weak var backButton: UIBarButtonItem!
#IBAction func backAction(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
self.startScan()
}
func startScan() {
let filterCriteria = GCKFilterCriteria(forAvailableApplicationWithID: kReceiverAppID)
self.deviceScanner = GCKDeviceScanner(filterCriteria: filterCriteria)
if let deviceScanner = self.deviceScanner {
deviceScanner.add(self)
deviceScanner.startScan()
print("scanning started")
deviceScanner.passiveScan = true
}
}
// MARK: GCKDeviceScannerListener
func deviceDidComeOnline(_ device: GCKDevice) {
print("deviceDidComeOnline")
print("Device found: \(device.friendlyName)");
self.updateButtonStates()
}
func deviceDidGoOffline(_ device: GCKDevice) {
print("deviceDidGoOffline()")
print("Device went away: \(device.friendlyName)");
self.updateButtonStates()
}
func deviceDidChange(_ device: GCKDevice) {
print("deviceDidChange()");
}
func updateButtonStates() {
print("updateButton")
if (deviceScanner!.devices.count > 0) {
// Show the Cast button.
navigationItem.rightBarButtonItems = [googleCastButton!]
if (deviceManager != nil && deviceManager?.connectionState == GCKConnectionState.connected) {
// Show the Cast button in the enabled state.
googleCastButton!.tintColor = UIColor.blue
} else {
// Show the Cast button in the disabled state.
googleCastButton!.tintColor = UIColor.gray
}
} else{
// Don't show Cast button.
navigationItem.rightBarButtonItems = []
}
}
}
Thank you in advance for any help or tips you can give me.
Best regards
UPDATE:
I have modified my code base to follow google v3 guidelines.
I now instantiate a GCKCastContext in AppDelegate in order to use google widgets.
But It seems that GCKCastContext or functionalities associated with the singleton are never called after initialising it. I have tried to add the GCKDiscoveryManagerListener to my AppDelegate to see if was detecting my ChromeCast device.
The code for my AppDelegate is :
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GCKLoggerDelegate,GCKDiscoveryManagerListener {
var window: UIWindow?
fileprivate let kReceiverAppID = "XXXXXXXXXX"
var discoveryManager: GCKDiscoveryManager
override init(){
let options:GCKCastOptions = GCKCastOptions(receiverApplicationID: kReceiverAppID)
GCKCastContext.setSharedInstanceWith(options)
self.discoveryManager = GCKCastContext.sharedInstance().discoveryManager
super.init()
self.discoveryManager.add(self)
self.discoveryManager.passiveScan = true
self.discoveryManager.startDiscovery()
GCKLogger.sharedInstance().delegate = self
}
.....
func log(fromFunction function: UnsafePointer<Int8>, message: String) {
let functionName = String(cString: function)
print(functionName + " - " + message);
}
func didUpdateDeviceList() {
print("didUpdateDeviceList with \(discoveryManager.deviceCount) devices")
(0..<discoveryManager.deviceCount).forEach { index in
print(index, discoveryManager.device(at: index))
}
}
func didStartDiscoveryForDeviceCategory(deviceCategory: String) {
print("GCKDiscoveryManagerListener: \(deviceCategory)")
print("FOUND: \(self.discoveryManager.hasDiscoveredDevices)")
}
func willUpdateDeviceList(){
print("will update device was called")
}
}
The functions didUpdateDeviceList, didStartDiscoveryForDeviceCategory
, willUpdateDeviceList are never called, meaning no Chrome device is ever found making the widgets unusable.
Thank again for any help

first portion of If statement is being passed over; optional error

First off, here is a link to my simple little GPA project: https://www.dropbox.com/sh/prkf2e3u6ok7jmo/AACY8b8_kDfigxluJyEzdZbGa?dl=0 .
import UIKit
class calccontroller: UIViewController {
#IBOutlet weak var GPA1: UITextField!
#IBOutlet weak var Credits1: UITextField!
#IBOutlet weak var GPA2: UITextField!
#IBOutlet weak var Credits2: UITextField!
#IBOutlet weak var answerLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func calculatorButton(sender: AnyObject) {
if GPA1 == nil || GPA2 == nil || Credits1 == nil || Credits2 == nil {
let title = "Oops"
let message = "Please add a value to each text field"
let okText = "OK"
let alert = UIAlertController(title: title, message: message, preferredStyle: UIAlertControllerStyle.Alert)
let okayButton = UIAlertAction(title: okText, style: UIAlertActionStyle.Cancel, handler: nil)
alert.addAction(okayButton)
presentViewController(alert, animated: true, completion: nil)
}
else
{
let gpa1text = Float(GPA1.text!)!
let gpa2text = Float(GPA2.text!)!
let credits1text = Float(Credits1.text!)!
let credits2text = Float(Credits2.text!)!
let firstGrade = gpa1text * credits1text
let secondGrade = gpa2text * credits2text
let allGPA = firstGrade + secondGrade
let allCredits = credits1text + credits2text
let finalGrade = allGPA / allCredits
answerLabel.text = "\(finalGrade)"
GPA1.resignFirstResponder()
GPA2.resignFirstResponder()
Credits1.resignFirstResponder()
Credits2.resignFirstResponder()
}
}
}
Anyways, I have a simple 4 text field, 1 button, and 1 label set up. I thought I had my code set up successfully that if each text field was not holding a value, a ui alert value would pop up asking for a value in each text box. If there are 4 values, then the app would complete the "math." However, when I leave all 4 empty or if I click the button when all 4 are filled and then delete 1 text field, my app crashes... "unexpectedly found nil while unwrapping an Optional value". I find it frustrating (which could be a simple mistake on my end, but in my mind I shouldn't be having this value this my pop up alert is meant to be used when a text field is nil.
Thank you for your time, Jon.
Your if logic is incorrect.
Since you create IBOutlet and check for nil, it will always return false if you instantiate your View Controller from storyboard or nib.
What you want to do is check its value is empty or not. So something like this should do the trick
if GPA1.text.isEmpty || GPA2.text.isEmpty || Credits1.text.isEmpty || Credits2.text.isEmpty {
// show alert
} else {
// do your calculation
}

Resources