View is not displayed - ios

I have an alert box that takes user input and starts a download task. After the user clicks "Ok," I want the screen to show a UIView that I added an ActivityIndicator to while the download occurs. The download occurs successfully and the function correctly opens up the next controller, however, the custom view nor activity indicator are ever displayed. Here's my code:
private func getKeyFromAlert() {
let alert = UIAlertController(title: "Enter Key", message: "Enter your text key below. If you want to scan it instead, click \"Scan Key.\" ", preferredStyle: .alert)
alert.addTextField { (textField) in
let attribString = NSAttributedString(string: "Enter your app code here")
textField.attributedPlaceholder = attribString
}
let scanAction = UIAlertAction(title: "Scan Key", style: .default) { _ in
self.openSettingsForApp()
}
let okAction = UIAlertAction(title: "OK", style: .default) { _ in
let textField = alert.textFields![0]
if let text = textField.text {
let encoded = text.toBase64()
let status = APIKeychain.storeToken(encoded)
if !status {
self.displayAlertForBadKeychain(useCamera: false)
} else {
self.addLoader()
self.dismissSetup()
}
} else {
let _ = APIKeychain.storeToken("")
self.addLoader()
self.dismissSetup()
}
}
alert.addAction(scanAction)
alert.addAction(okAction)
show(alert, sender: nil)
}
The function in question that I use to display the UIView is addLoader()
The code for addLoader is:
private func addLoader() {
let frame = CGRect(x: 0, y: 0, width: view.bounds.width, height: view.bounds.height)
let loaderView = UIView(frame: frame)
loaderView.alpha = 1.0
loaderView.backgroundColor = UIColor.white
let activitySpinner: UIActivityIndicatorView = UIActivityIndicatorView(frame: loaderView.frame)
activitySpinner.center = loaderView.center
activitySpinner.hidesWhenStopped = false
activitySpinner.style = .whiteLarge
activitySpinner.startAnimating()
loaderView.addSubview(activitySpinner)
self.view.addSubview(loaderView)
self.view.layoutIfNeeded()
}
I've tried several iterations of setNeedsDisplay and setNeedsLayout without luck. I've also tried explicitly declaring this in a DispatchQueue.main.async without any affect as well.
EDIT
I added the code below for dismissSetup()
private func dismissSetup() {
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
DispatchQueue.global(qos: .background).async {
if self.updateDatabase {
//This will start the download process
let _ = WebDataFetcher(dataStack: self.dataStack)
}
dispatchGroup.leave()
}
dispatchGroup.wait()
let mainSB = UIStoryboard(name: "UserInputs", bundle: nil)
let mainVC = mainSB.instantiateViewController(withIdentifier: "userInputs")
appDelegate.window?.rootViewController = mainVC
}

Related

largeTitleTextAttributes disappear after programmatic push - Swift

I'm pushing to a navigation controller and the large title I have set within the shootSummary VC text attributes change without warning -- they lose their original formatting. So I've tried putting them as I've done here after the push, but that hasn't worked either. Here's my code:
guard let shootSummaryVC = storyboard?.instantiateViewController(withIdentifier: "ShootPVC") as? ShootPVC else { return }
guard let indexPath = tableView.indexPathForSelectedRow else { return }
guard let shootID = shoots?[indexPath.row].id else { return }
shootSummaryVC.id = shootID
shootSummaryVC.initialPage = 3
DispatchQueue.main.async { [self] in
navigationController?.pushViewController(shootSummaryVC, animated: true)
navigationController?.hidesNavigationBarHairline = true
navigationController?.navigationBar.topItem?.backBarButtonItem =
UIBarButtonItem(title: "Track Payments", style: .plain, target: nil, action: nil)
let p = NSMutableParagraphStyle()
p.firstLineHeadIndent = 10
navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.font: currentTheme.titleFontLarge, NSAttributedString.Key.foregroundColor: currentTheme.navigationBarTextColor, NSAttributedString.Key.paragraphStyle: p]
}
The largeTitleTextAttributes in my attempted solution above don't affect the title. I tried setting them within the VC being pushed to (shootSummaryVC) but that hasn't worked either. Any ideas?

Cant get uIAlertAction to work textfield will only read first and last element

Im doing an IOS contact app and I want the user to able to change there quick information from an alert my problem is that I cannot get my alertAction to read anything beside the first and last element
let add = UIAlertAction(title: "Add", style: .default) { _ in
guard
let name = alert.textFields?.first?.text,
let address = alert.textFields?.first?.text,
let state = alert.textFields?.first?.text,
let city = alert.textFields?.first?.text,
let zip = alert.textFields?.first?.text,
let phoneString=alert.textFields?.last?.text,
let phone = Int(phoneString)
else { return }
I know that alert.textField?.first.text returns the first element and alert.textField?.last.text returns my last element ,so what ever goes in my name and phone textField is good , but how can I return the elements that go in to my address , state , city and zip text fields?
You can add tag to each of your textFields. And then utilize it, you can enumerate your textFields in your alert object. For example:
let alert = UIAlertController(title: "Add New Name", message: "", preferredStyle: .alert)
alert.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "Enter Name"
textField.tag = 0
}
alert.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "Enter Address"
textField.tag = 1
}
alert.addTextField { (textField : UITextField!) -> Void in
textField.placeholder = "Enter State"
textField.tag = 2
}
let saveAction = UIAlertAction(title: "Save", style: .default, handler: { _ -> Void in
guard let name = alert.textFields?.filter({ $0.tag == 0 }).first?.text,
let address = alert.textFields?.filter({ $0.tag == 1 }).first?.text,
let state = alert.textFields?.filter({ $0.tag == 2 }).first?.text else { return }
/////
})
alert.addAction(saveAction)
self.present(alert, animated: true, completion: nil)
OR
let name = alert.textFields?[0].text ?? ""
let address = alert.textFields?[1].text ?? ""
let state = alert.textFields?[2].text ?? ""
You can add multiple textfields inside a UIAlertController. UIAlertController has a property "textFields" which is basically a array of all added TextFields.
You can add a textfield using this code -
let alert = UIAlertController(title: "Alert", message: "Hi", preferredStyle: .alert)
alert.addTextField { (textFieldName) in
// Configure it here
}
alert.addTextField { (textFieldAddress) in
}
alert.addTextField { (textfieldCity) in
}
The order in which you add the textFields ,will be same when you will access the textfields using "textField" property.

Getting duplicate tableview cells after first time

In my app, there is an add button, when clicked will add a new tableviewcell. However the problem is I am getting duplicate cells after the first time. Essentially, I am getting 2 duplicates when I click second time, 3 on third and so on.... Please see the images for the screenshot:
The above image is the first screen. Clicking '+' will add a new cell, which looks like the below images:
Now after saving,
Now if I go out of this view and come back, click add again and create a new cell, it gives me duplicates as mentioned in the above paragraphs (that is, 2 for second time, 3 for third time and so on...).
Here is the screenshot:
Here is the code I am using:
#IBAction func addBasket(_ sender: UIButton) {
let prefs = UserDefaults.standard
let status = prefs.string(forKey: "status")
if(status != nil){
if( status == "pending"){
if(BasketItemList.count < 5 ) {
self.addpost()
} else {
let alert = SCLAlertView()
alert.showWarning("Basket", subTitle: "Upgrade to add more")
}
} else {
if(BasketItemList.count < 50 ) {
self.addpost()
} else {
let alert = SCLAlertView()
alert.showWarning("Basket", subTitle: "Upgrade to add more")
}
}
}
}
func addpost() {
let appearance = SCLAlertView.SCLAppearance(
showCloseButton: false
)
let alert = SCLAlertView(appearance : appearance)
let txt = alert.addTextField("Enter name")
alert.addButton("Save") {
if txt.text?.characters.count != 0 {
let basketname : String = txt.text!
let userID = FIRAuth.auth()?.currentUser?.uid
let postitem : [String :AnyObject] = ["userid" : userID! as AnyObject , "basketname" : basketname as AnyObject ]
let dbref = FIRDatabase.database().reference()
dbref.child("BasketList").childByAutoId().setValue(postitem)
self.Basketdata2()
let appearance = SCLAlertView.SCLAppearance(
kDefaultShadowOpacity: 0,
showCloseButton: false
)
let alertView = SCLAlertView(appearance: appearance)
alertView.showTitle(
"Saved", // Title of view
subTitle: "", // String of view
duration: 2.0, // Duration to show before closing automatically, default: 0.0
completeText: "Done", // Optional button value, default: ""
style: .success, // Styles - see below.
colorStyle: 0xA429FF,
colorTextButton: 0xFFFFFF
)
} else {
let alert = SCLAlertView()
alert.showError("Oops!", subTitle: "Basket name should not be empty")
self.tableviewbasket.reloadData()
}
}
alert.addButton("Cancel"){
}
alert.showEdit("Add basket", subTitle: "Please enter your basket name")
}
func Basketdata2() {
HUD.show(.labeledProgress(title: "Loading...", subtitle: ""))
let databaseref = FIRDatabase.database().reference()
var userID = FIRAuth.auth()?.currentUser?.uid
if userID == nil {
userID = userfbid
}
databaseref.child("BasketList").queryOrdered(byChild: "userid").queryEqual(toValue: userID!).observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
self.tableviewbasket.backgroundView = nil;
HUD.hide()
} else {
HUD.hide()
self.tableviewbasket.setContentOffset(CGPoint(x : 0, y: -98), animated: true)
if (self.BasketItemList.count == 0) {
// tableView is empty. You can set a backgroundView for it.
let label = UILabel(frame: CGRect(x: 5, y: 0, width: self.tableviewbasket.bounds.size.width, height:self.tableviewbasket.bounds.size.height))
label.text = "The best preparation for tomorrow \n is doing your best today.\n Please create your first basket."
label.textColor = UIColor.black;
label.textAlignment = .center
label.numberOfLines = 4
label.sizeToFit()
label.font = UIFont(name: "AvenirNext-Regular", size: 16.0)
self.tableviewbasket.backgroundView = label;
self.tableviewbasket.separatorStyle = .none;
}
}
})
}
func Basketdata() {
HUD.show(.labeledProgress(title: "Please wait...", subtitle: ""))
self.BasketItemList.removeAll()
self.Basketid.removeAll()
let databaseref = FIRDatabase.database().reference()
let userID = FIRAuth.auth()?.currentUser?.uid
databaseref.child("BasketList").queryOrdered(byChild: "userid").queryEqual(toValue: userID!).observeSingleEvent(of: .value, with: { (snapshot) in
if snapshot.exists() {
databaseref.child("BasketList").queryOrdered(byChild: "userid").queryEqual(toValue: userID!).observe(.childAdded, with: {
(snapshot) in
if let dictionary = snapshot.value as? [String : AnyObject] {
let basketitem = BasketList(text : "")
basketitem.setValuesForKeys(dictionary)
self.BasketItemList.append(basketitem)
self.Basketid.append(snapshot.key)
DispatchQueue.main.async {
if !self.BasketItemList.isEmpty {
HUD.hide()
self.tableviewbasket.reloadData()
}
}
} else {
self.tableviewbasket.reloadData()
HUD.hide()
}
})
} else {
if (self.BasketItemList.count == 0) {
// tableView is empty. You can set a backgroundView for it.
let label = UILabel(frame: CGRect(x: 5, y: 0, width: self.tableviewbasket.bounds.size.width, height:self.tableviewbasket.bounds.size.height))
label.text = "The best preparation for tomorrow \nis doing your best today"
label.textColor = UIColor.black;
label.textAlignment = .center
label.numberOfLines = 2
label.sizeToFit()
label.font = UIFont(name: "AvenirNext-Regular", size: 16.0)
self.tableviewbasket.backgroundView = label;
self.tableviewbasket.separatorStyle = .none;
}
HUD.hide()
}
})
}
Can someone help me understand what is wrong with my code? Thanks!
Edit: I have referred this thread without any luck: Getting duplicate cells with UITableViewController cellForRowAtIndexPath
Edit 2: Also, when I come out of that view and go to the same view, the duplicate values are vansihed.
Edit 3: Tried the answer without any success.
Follow below steps:
When you'r getting data from firebase db, first remove your array all objects that you'r using in the cellForRow method. In your case i think it should be array of Bucket (not sure).
Assign data to your object
reload tableview.
Reason of replication of data.
let your bucket have 2 values and it is stored inDB. When you fetch data from DB it gives you all the values i.e. 1,2,3. Now you adds these now your array will be 1,2,1,2,3.
Thats what happening in your case.

Cannot Find Pdf File being created in Swift XCode

Iv used the following Code from Tom to create a Pdf File and
PDF Generation Swift
im having the same problem finding the document I created using Tom's code. Iv search my Mac HD and still no document and the programme does not crash. And when i look at the log it shows it has been stored at the following path
pdfPathWithFileName String "/Users/cleota/Library/Developer/CoreSimulator/Devices/B72A97D0-339E-4E79-AED6-4991D3B7C4B7/data/Containers/Data/Application/7A7789C4-27C5-45FB-8604-E36865609764/Documents/Ezy Essay Test.pdf"
but when I go there these folders(Library/Developer/CoreSimulator/Devices)are not there where it says it has been stored. Thoughts please?
#IBAction func createPdfDocument(sender: AnyObject) {
let fileName: String = "Taumaoe.pdf"
let path:NSArray = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
let documentDirectory: AnyObject = path.objectAtIndex(0)
let pdfPathWithFileName = documentDirectory.stringByAppendingPathComponent(fileName as String)
print(pdfPathWithFileName)
generatePdf(pdfPathWithFileName)
}
func generatePdf(filepath: String){
UIGraphicsBeginPDFContextToFile(filepath, CGRectZero, nil)
UIGraphicsBeginPDFPageWithInfo(CGRectMake(0, 0, 850, 1100), nil)
drawBackground()
}
func drawBackground(){
var context:CGContextRef = UIGraphicsGetCurrentContext()!
// var rect:CGRect = CGRectMake(0, 0, CGSize.height, CGSize.width)
//CGContextSetFillColorWithColor(context, UIColor.greenColor().CGColor)
//CGContextFillRect(context, rect)
var testView = UIView (frame: CGRectMake(0,0,850,1100))
testView.backgroundColor = UIColor.yellowColor()
var label = UILabel (frame: CGRectMake(10,10,100,20))
label.textColor = UIColor.redColor()
label.backgroundColor = UIColor.lightGrayColor()
label.text = "I'am a test label"
testView.addSubview(label)
testView.layer.renderInContext(context)
UIGraphicsEndPDFContext()
//Title of 1st option of MainController
let sexyKeyWordscontroller = UIAlertController(title: "Ezy Essay Saved!", message: "Well done! Your Ezy Essay Pdf document has been saved at the following path: ", preferredStyle: UIAlertControllerStyle.Alert)
let closeButton : UIAlertAction = UIAlertAction(title: "Close",
style: UIAlertActionStyle.Cancel,
handler: {
(alert: UIAlertAction!) in sexyKeyWordscontroller.dismissViewControllerAnimated(true,
completion: nil)
})
sexyKeyWordscontroller.addAction(closeButton)
self.presentViewController(sexyKeyWordscontroller, animated: true, completion: nil)
}
Thanks
If you print out pdfPathWithFileName in the button event you will get the file path. When you have the file path open a finder window and in the file menu click: Go > Go to folder
The path that you have printed out will look something like this:
/Users/USERNAME/Library/Developer/CoreSimulator/Devices/...
Copy this into the Go to folder from the path
~/Library/Developer/CoreSimulator/Devices/...
And of course skip the last "/xp.pdf" in the path if you only want to open the location of the folder and not the file itself.

AlertController doesn't save textField text on save, only edit

I have an alertController with a textField. The user enters their data into the textField and hits "set". It should then create the item and save the text entered as my attribute it's set to. However, upon creating the item the textField passes nil. It's not saved until the item is reopened and saved again (prompting the alertController to request data in the textField). Why is it not saving it the first time?
saveButton pressed:
#IBAction func saveButton(sender: AnyObject) {
if (item?.slminqty == nil) {
let alert = UIAlertController(title: "Minimun Qty.", message: "Please set minimun qty. for pantry.", preferredStyle: UIAlertControllerStyle.Alert)
alert.addTextFieldWithConfigurationHandler { (textField: UITextField!) -> Void in
textField.placeholder = "Minimun Qty."
textField.keyboardType = .NumbersAndPunctuation
textField.clearButtonMode = UITextFieldViewMode.WhileEditing
}
alert.addAction(UIAlertAction(title: "Dismiss", style: UIAlertActionStyle.Default, handler: {saveitem}()))
alert.addAction(UIAlertAction(title: "Set", style: UIAlertActionStyle.Default, handler: {(action) -> Void in
let textField = alert.textFields![0].text!
self.item?.slminqty = textField
self.saveitem(self)}))
self.presentViewController(alert, animated: true, completion: nil)
}else{
if item != nil {
edititems()
} else {
createitems()
}
print(item?.slminqty)
dismissVC()
}
}
Save function:
func saveitem(sender: AnyObject) {
if item != nil {
edititems()
} else {
createitems()
}
print(item?.slminqty)
dismissVC()
}
Create function:
func createitems() {
let entityDescription = NSEntityDescription.entityForName("List", inManagedObjectContext: moc)
let item = List(entity: entityDescription!, insertIntoManagedObjectContext: moc)
item.slitem = slitem.text
item.sldesc = sldesc.text
item.slqty = slqty.text
item.slprice = slprice.text
item.slist = true
item.slcross = false
if slitem.text == nil{
createitems()
}else{
edititems()
}
do {
try moc.save()
} catch _ {
return
}
}
Edit function:
func edititems() {
item?.slitem = slitem.text!
item?.sldesc = sldesc.text!
item?.slqty = slqty.text!
item?.slprice = slprice.text!
do {
try moc.save()
} catch {
return
}
}
If both of the create and edit are the same (with the exception of slcross and slist) why won't it save the data when the item is created?
Edit please see my pull reqest, I have made some changes to your code. along with some comments.
I think the problem in this line :
self.item?.slminqty = textField
self.item might be nil. you should make sure first item is not nil.
you may try to create item if this is nil. like:
if self.item == nil {
//create item.
self.acreateItems()
// after creating the item just test its value.
print("item was nil so we just created it.\nIts value not is \(self.item)")
}
self.item?.slminqty = textField

Resources