UITextView Placeholder did not dissapear after clicked - ios

this is my code in xcode with swift 2. please see it first.
import UIKit
class sendComplaintViewController: UIViewController, UITextViewDelegate {
    #IBOutlet weak var subjectTextField: UITextField!
    #IBOutlet weak var typeDropDown: IQDropDownTextField!
    #IBOutlet weak var messageTextView: UITextView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        typeDropDown.isOptionalDropDown = false
        typeDropDown.itemList = ["Choose Category","Complaint", "Suggestion"]
        // Do any additional setup after loading the view.
        messageTextView.text = "Placeholder"
        messageTextView.textColor = UIColor.lightGrayColor()
        
        messageTextView.becomeFirstResponder()
        
        messageTextView.selectedTextRange = messageTextView.textRangeFromPosition(messageTextView.beginningOfDocument, toPosition: messageTextView.beginningOfDocument)
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
    //placeholder textview
    func messageTextView(messageTextView: UITextView, shouldChangeTextInRange range: NSRange, replacementText text: String) -> Bool {
        // Combine the textView text and the replacement text to
        // create the updated text string
        let currentText:NSString = messageTextView.text
        let updatedText = currentText.stringByReplacingCharactersInRange(range, withString:text)
        
        // If updated text view will be empty, add the placeholder
        // and set the cursor to the beginning of the text view
        if updatedText.isEmpty {
            messageTextView.text = "Placeholder"
            messageTextView.textColor = UIColor.lightGrayColor()
            
            messageTextView.selectedTextRange = messageTextView.textRangeFromPosition(messageTextView.beginningOfDocument, toPosition: messageTextView.beginningOfDocument)
            
            return false
        }
            
            // Else if the text view's placeholder is showing and the
            // length of the replacement string is greater than 0, clear
            // the text view and set its color to black to prepare for
            // the user's entry
        else if messageTextView.textColor == UIColor.lightGrayColor() && !text.isEmpty {
            messageTextView.text = nil
            messageTextView.textColor = UIColor.blackColor()
        }
        
        return true
    }
    func textViewDidChangeSelection(messageTextView: UITextView) {
        if self.view.window != nil {
            if messageTextView.textColor == UIColor.lightGrayColor() {
                messageTextView.selectedTextRange = messageTextView.textRangeFromPosition(messageTextView.beginningOfDocument, toPosition: messageTextView.beginningOfDocument)
            }
        }
    }
    //border textview
    
    override func viewDidLayoutSubviews() {
        // Creates the bottom border
        let borderBottom = CALayer()
        let borderWidth = CGFloat(2.0)
        borderBottom.borderColor = UIColor.grayColor().CGColor
        borderBottom.frame = CGRect(x: 0, y: messageTextView.frame.height - 1.0, width: messageTextView.frame.width , height: messageTextView.frame.height - 1.0)
        borderBottom.borderWidth = borderWidth
        messageTextView.layer.addSublayer(borderBottom)
        messageTextView.layer.masksToBounds = true
        
        // Creates the Top border
        let borderTop = CALayer()
        borderTop.borderColor = UIColor.grayColor().CGColor
        borderTop.frame = CGRect(x: 0, y: 0, width: messageTextView.frame.width, height: 1)
        borderTop.borderWidth = borderWidth
        messageTextView.layer.addSublayer(borderTop)
        messageTextView.layer.masksToBounds = true
    }
    /*
    // MARK: - Navigation
    // In a storyboard-based application, you will often want to do a little preparation before navigation
    override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
        // Get the new view controller using segue.destinationViewController.
        // Pass the selected object to the new view controller.
    }
    */
    #IBAction func sendButtonTapped(sender: AnyObject){
        
        //let controltype = controlTypeTextField.selectedItem
        let subject = subjectTextField.text
        let type = typeDropDown.selectedItem
        let complaintMessage = messageTextView.text
        let userId = NSUserDefaults.standardUserDefaults().stringForKey("userId")
       
        if(type == nil || type! == "Choose Category"){
            displayAlertMessage("Please Choose Category")
            return
        }
        if(subject!.isEmpty || type!.isEmpty || complaintMessage!.isEmpty){
            //display an alert message
            displayAlertMessage("All fields are requiered to fill in")
            return
        }
        
        //input fungsi mbprog
        let spinningActivity = MBProgressHUD.showHUDAddedTo(self.view, animated: true)
        spinningActivity.labelText = "Loading"
        spinningActivity.detailsLabelText = "Please wait"
        
        //Send HTTP POST
        
        let myUrl = NSURL(string: "");
        let request = NSMutableURLRequest(URL:myUrl!);
        request.HTTPMethod = "POST";
        
        request.HTTPBody = postString.dataUsingEncoding(NSUTF8StringEncoding);
        NSURLSession.sharedSession().dataTaskWithRequest(request, completionHandler: { (data:NSData?, response:NSURLResponse?, error:NSError?) -> Void in
            
            dispatch_async(dispatch_get_main_queue()){
                
                spinningActivity.hide(true) //waiting send data to server (signup)
                
                if error != nil{
                    self.displayAlertMessage(error!.localizedDescription)
                    return
                }
                
                do {
                    let json = try NSJSONSerialization.JSONObjectWithData(data!, options: .MutableContainers) as? NSDictionary
                    
                    if let parseJSON = json {
                        
                        let complaintId = parseJSON["complaintId"] as? String
                        
                        if( complaintId != nil)
                        {
                            let myAlert = UIAlertController(title: "Alert", message: "Success!", preferredStyle: UIAlertControllerStyle.Alert);
                            
                            let okAction = UIAlertAction(title: "OK", style: UIAlertActionStyle.Default){(action) in
                                
                                self.dismissViewControllerAnimated(true, completion: nil)
                            }
                            
                            myAlert.addAction(okAction);
                            self.presentViewController(myAlert, animated: true, completion: nil)
                        } else {
                            let errorMessage = parseJSON["message"] as? String
                            if(errorMessage != nil)
                            {
                                self.displayAlertMessage(errorMessage!)
                            }
                        }
                    }
                } catch{
                    //print(error)
                    print(error)
                    
                    if data != nil {
                        let string = String(data: data!, encoding: NSUTF8StringEncoding)
                        print(string)
                    }
                    
                    print(response)
                }
            }
            
        }).resume()
    }
    
    #IBAction func cancelButtonTapped(sender: AnyObject) {
        self.dismissViewControllerAnimated(true, completion: nil)
    }
    
    func displayAlertMessage(userMessage:String){
        let myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.Alert);
        let okAction = UIAlertAction(title: "ok", style: UIAlertActionStyle.Default, handler: nil)
        myAlert.addAction(okAction);
        self.presentViewController(myAlert, animated: true, completion: nil)
    }
}
Is there any error in my code that makes placeholder didn't working right?
Placeholder is already showing but it didn't disappear after clicked.
thank you.

You are setting the text of your TextView, not the placeholder.
This piece of code messageTextView.text = "Placeholder" sets the text not the placeholder
If your view is a UITextView, then check this question Text View Placeholder Swift

You can use HCExtentionSwift for that it easy. You can check GitHub link for that pod here
Step 1 Install pod 'HCExtentionSwift'
Step 2 Go to Identity Inspector
Step 3 Insert class name TextViewDesign
Now after doing 3 steps you will see changes in Attribute Inspector
From there you can insert PlaceHolder Value

Related

View is not displayed

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
}

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.

Swift 3 increment increment tab bar badge [duplicate]

#IBAction func addToCart(sender: AnyObject) {
let itemObjectTitle = itemObject.valueForKey("itemDescription") as! String
let alertController = UIAlertController(title: "Add \(itemObjectTitle) to cart?", message: "", preferredStyle: .Alert)
let yesAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default) { (action) in
var tabArray = self.tabBarController?.tabBar.items as NSArray!
var tabItem = tabArray.objectAtIndex(1) as! UITabBarItem
let badgeValue = "1"
if let x = badgeValue.toInt() {
tabItem.badgeValue = "\(x)"
}
}
I don't know why I can't just do += "(x)"
Error:
binary operator '+=' cannot be applied to operands of type 'String?' and 'String'
I want it to increment by 1 each time the user selects "Yes". Right now obviously it just stays at 1.
You can try to access the badgeValue and convert it to Integer as follow:
Swift 2
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
nextValue = Int(badgeValue)?.successor() {
tabBarController?.tabBar.items?[1].badgeValue = String(nextValue)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
Swift 3 or later
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
let value = Int(badgeValue) {
tabBarController?.tabBar.items?[1].badgeValue = String(value + 1)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
To delete the badge just assign nil to the badgeValue overriding viewDidAppear method:
override func viewDidAppear(animated: Bool) {
tabBarController?.tabBar.items?[1].badgeValue = nil
}
Works with Swift 2:
let tabController = UIApplication.sharedApplication().windows.first?.rootViewController as? UITabBarController
let tabArray = tabController!.tabBar.items as NSArray!
let alertTabItem = tabArray.objectAtIndex(2) as! UITabBarItem
if let badgeValue = (alertTabItem.badgeValue) {
let intValue = Int(badgeValue)
alertTabItem.badgeValue = (intValue! + 1).description
print(intValue)
} else {
alertTabItem.badgeValue = "1"
}

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

Increment tab bar badge w/ UIAlertAction swift?

#IBAction func addToCart(sender: AnyObject) {
let itemObjectTitle = itemObject.valueForKey("itemDescription") as! String
let alertController = UIAlertController(title: "Add \(itemObjectTitle) to cart?", message: "", preferredStyle: .Alert)
let yesAction = UIAlertAction(title: "Yes", style: UIAlertActionStyle.Default) { (action) in
var tabArray = self.tabBarController?.tabBar.items as NSArray!
var tabItem = tabArray.objectAtIndex(1) as! UITabBarItem
let badgeValue = "1"
if let x = badgeValue.toInt() {
tabItem.badgeValue = "\(x)"
}
}
I don't know why I can't just do += "(x)"
Error:
binary operator '+=' cannot be applied to operands of type 'String?' and 'String'
I want it to increment by 1 each time the user selects "Yes". Right now obviously it just stays at 1.
You can try to access the badgeValue and convert it to Integer as follow:
Swift 2
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
nextValue = Int(badgeValue)?.successor() {
tabBarController?.tabBar.items?[1].badgeValue = String(nextValue)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
Swift 3 or later
if let badgeValue = tabBarController?.tabBar.items?[1].badgeValue,
let value = Int(badgeValue) {
tabBarController?.tabBar.items?[1].badgeValue = String(value + 1)
} else {
tabBarController?.tabBar.items?[1].badgeValue = "1"
}
To delete the badge just assign nil to the badgeValue overriding viewDidAppear method:
override func viewDidAppear(animated: Bool) {
tabBarController?.tabBar.items?[1].badgeValue = nil
}
Works with Swift 2:
let tabController = UIApplication.sharedApplication().windows.first?.rootViewController as? UITabBarController
let tabArray = tabController!.tabBar.items as NSArray!
let alertTabItem = tabArray.objectAtIndex(2) as! UITabBarItem
if let badgeValue = (alertTabItem.badgeValue) {
let intValue = Int(badgeValue)
alertTabItem.badgeValue = (intValue! + 1).description
print(intValue)
} else {
alertTabItem.badgeValue = "1"
}

Resources