Hangman Game letters reset each time the button is pressed [duplicate] - ios

This question already exists:
I am making a HangMan game and I'm having problems with letters being doubled each time it loops [closed]
Closed last month.
So I've been creating a hangman game and been having problems with each time a user guesses a correct letter again, the previous correct letter/letters gets removed.??
I tried a lot of if elses to hold each index of the letter and append if its correct but that did not work. So in general let's say a user got their first letter correct which was A. This is what happens..
XXXAXXAX
But the Second letter they get correct, lets say B this happens...
XBXXXXXX
they are supposed to bring A along to the next iteration and so onn.
can anyone see what's the problem? Here's my code below..
class ViewController: UIViewController {
var allWords = [String]()
var usedLetters = [String]()
var startWords = [String]()
var promptWord = String()
var randomWord = ""
override func viewDidLoad() {
super.viewDidLoad()
EnterGuess()
fileWork()
print(randomWord)
title = "GUESS A Letter: ?????????)"
}
func fileWork() {
if let startWordsURL = Bundle.main.url(forResource: "start", withExtension: "txt") {
if let startWords = try? String(contentsOf: startWordsURL) {
allWords = startWords.components(separatedBy: "\n")
let wordssss = startWords.randomElement()
randomWord = allWords.randomElement()!
}
}
}
func EnterGuess() {
let ac = UIAlertController(title: "Guess a letter", message: nil, preferredStyle: .alert)
ac.addTextField()
var submitGuess = UIAlertAction(title: "Submit", style: .default) {_ in
guard var answer = ac.textFields?[0].text else {return }
answer
self.submit(answer)
self.EnterGuess()
}
ac.addAction(submitGuess)
present(ac, animated: true)
}
func submit(_ answer: String) {
let guessedLetter = answer
let wordArray = randomWord.map(String.init)
var hidden = Array(repeating: "x", count: randomWord.count)
for index in hidden.indices {
if wordArray[index] == answer {
hidden[index] = wordArray[index]
}
}
print(hidden.joined())
// print(wordArray)
title = String(describing: hidden.joined())
}
}

The problem is that you are "re-setting" the hidden string with each letter guess.
Instead, you want to create a class-level var:
var hidden = [String]()
and "re-set" it to "xxxxxx..." when you start a new game.
Then, with each guess, you'll be keeping the old letters and replacing new letters.
Suppose the game word is EASY:
hidden is "xxxx"
guessed letter is "A"
hidden goes from "xxxx" to "xAxx"
guessed letter is "Y"
hidden goes from "xAxx" to "xAxY"
guessed letter is "E"
hidden goes from "xAxY" to "EAxY"
and so on.
Here's a quick example you can run:
class HangmanViewController: UIViewController, UITextFieldDelegate {
var allWords: [String] = [
"easy",
"birthday",
"laboratory",
"hangman",
"iphone",
"requirements",
"gaming",
]
var usedLetters = [String]()
var startWords = [String]()
var promptWord = String()
var randomWord = ""
var hidden = [String]()
let tf = UITextField()
let progressLabel = UILabel()
let usedLabel = UILabel()
let newGameButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
tf.textAlignment = .center
tf.borderStyle = .roundedRect
tf.textAlignment = .center
tf.font = .monospacedSystemFont(ofSize: 24.0, weight: .light)
tf.delegate = self
progressLabel.textAlignment = .center
progressLabel.font = .monospacedSystemFont(ofSize: 24.0, weight: .light)
progressLabel.backgroundColor = .yellow
usedLabel.textAlignment = .center
usedLabel.font = .monospacedSystemFont(ofSize: 16.0, weight: .light)
usedLabel.backgroundColor = .cyan
newGameButton.setTitle("New Game", for: [])
newGameButton.setTitleColor(.white, for: .normal)
newGameButton.setTitleColor(.lightGray, for: .highlighted)
newGameButton.backgroundColor = .systemBlue
newGameButton.layer.cornerRadius = 8
newGameButton.layer.borderColor = UIColor.blue.cgColor
newGameButton.layer.borderWidth = 1
[tf, progressLabel, usedLabel, newGameButton].forEach { v in
v.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(v)
}
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
tf.widthAnchor.constraint(equalToConstant: 80.0),
tf.topAnchor.constraint(equalTo: g.topAnchor, constant: 80.0),
tf.centerXAnchor.constraint(equalTo: g.centerXAnchor),
progressLabel.widthAnchor.constraint(equalToConstant: 300.0),
progressLabel.topAnchor.constraint(equalTo: tf.bottomAnchor, constant: 40.0),
progressLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
usedLabel.widthAnchor.constraint(equalToConstant: 300.0),
usedLabel.topAnchor.constraint(equalTo: progressLabel.bottomAnchor, constant: 40.0),
usedLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
newGameButton.widthAnchor.constraint(equalToConstant: 200.0),
newGameButton.topAnchor.constraint(equalTo: usedLabel.bottomAnchor, constant: 40.0),
newGameButton.centerXAnchor.constraint(equalTo: g.centerXAnchor),
])
newGameButton.addTarget(self, action: #selector(newGameTapped(_:)), for: .touchUpInside)
newGame()
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// upper-case the entered letter
let s = string.uppercased()
// we don't want to process if a string was pasted into the field
if s.count != 1 {
return false
}
// only allow A - Z
if s.rangeOfCharacter(from: .uppercaseLetters) == nil {
return false
}
// replace the current text
textField.text = s
// process the entered letter
submit(s)
// don't let the textfield process the string
return false
}
func newGame() {
// cycle the array of game words
allWords.append(allWords.removeFirst())
// safely unwrap
guard let w = allWords.first else {
fatalError("Bad setup")
}
// upper-case the word
randomWord = w.uppercased()
// set hidden string to "####..."
hidden = Array(repeating: "#", count: randomWord.count)
// clear used letters
usedLetters = []
// update the game progress label
progressLabel.text = String(hidden.joined())
progressLabel.textColor = .black
// update used letters label
usedLabel.text = " "
// hide the new game button
newGameButton.isHidden = true
// re-enable text field
tf.isUserInteractionEnabled = true
// for development
print("New Game Word is:", randomWord)
}
func submit(_ answer: String) {
if usedLetters.contains(answer) {
return
}
usedLetters.append(answer)
usedLabel.text = usedLetters.joined()
let wordArray = randomWord.map(String.init)
for index in hidden.indices {
if wordArray[index] == answer {
hidden[index] = wordArray[index]
}
}
progressLabel.text = hidden.joined()
if hidden == wordArray {
progressLabel.textColor = .red
// clear and disable text field
tf.text = ""
tf.isUserInteractionEnabled = false
// dismiss keyboard
view.endEditing(true)
// show the new game button
newGameButton.isHidden = false
}
}
#objc func newGameTapped(_ sender: UIButton) {
newGame()
}
}
It will look about like this (the cyan label will show the used letters). I'll type T, R, Y, S, M, E, A:

Related

How To Add [int:int] element in user Defaults in swift5

I used to many attempts to solve this error but i can't.
i have [Int: Int] dictionary
want's to add this dictionary to default for use latter
Sample Code Of mine
var ListIds = [Int: Int]()
ListIds[1] = 1
defaults.set(["data": ListIds], forKey: "cartKeys")
Some quick web searching and I found this: Hacking with Swift forums - Save [Int:Int] to UserDefaults
I edited the code slightly to make it an extension, and to allow passing the Key to use in UserDefaults:
extension UserDefaults {
func saveIntDictionary(key: String, intDictionary: [Int:Int]) {
let encoder = PropertyListEncoder()
guard let data = try? encoder.encode(intDictionary) else {
return
}
set(data, forKey: key)
}
func retrieveSavedIntDictionary(key: String) -> [Int:Int]? {
let decoder = PropertyListDecoder()
guard let data = data(forKey: key),
let intDictionary = try? decoder.decode([Int:Int].self, from: data) else {
return nil
}
return intDictionary
}
}
and it can be used like this:
// note: it returns an optional -- it will be nil if the key does not exist
// handle that appropriately
let sv = UserDefaults.standard.retrieveSavedIntDictionary(key: "cartKeys")
// save to UserDefaults
UserDefaults.standard.saveIntDictionary(key: "cartKeys", intDictionary: listIDs)
Here's a quick runnable example:
class ViewController: UIViewController {
var listIDs: [Int : Int] = [:]
// a scrollable non-editable text view to display the dictionary
let displayTextView = UITextView()
override func viewDidLoad() {
super.viewDidLoad()
if let sv = UserDefaults.standard.retrieveSavedIntDictionary(key: "cartKeys") {
listIDs = sv
print("Loaded from UserDefaults!")
print(String(describing: listIDs))
print()
} else {
print("Nothing in UserDefaults")
print()
}
// let's have two buttons
// Add a new ID
// Reset (clears the dictionary)
let b1 = UIButton()
b1.setTitle("Add a new ID", for: [])
b1.setTitleColor(.white, for: .normal)
b1.setTitleColor(.lightGray, for: .highlighted)
b1.backgroundColor = .systemBlue
b1.layer.cornerRadius = 8
b1.addTarget(self, action: #selector(addEntry(_:)), for: .touchUpInside)
let b2 = UIButton()
b2.setTitle("Reset", for: [])
b2.setTitleColor(.white, for: .normal)
b2.setTitleColor(.lightGray, for: .highlighted)
b2.backgroundColor = .systemRed
b2.layer.cornerRadius = 8
b2.addTarget(self, action: #selector(reset(_:)), for: .touchUpInside)
displayTextView.backgroundColor = .yellow
displayTextView.font = .monospacedSystemFont(ofSize: 16.0, weight: .regular)
displayTextView.isEditable = false
// a stack view for the buttons and display text view
let stack = UIStackView(arrangedSubviews: [b1, displayTextView, b2])
stack.axis = .vertical
stack.spacing = 12
stack.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(stack)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
stack.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 40.0),
stack.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -40.0),
stack.centerYAnchor.constraint(equalTo: g.centerYAnchor, constant: -20.0),
displayTextView.heightAnchor.constraint(equalToConstant: 240.0),
])
updateDisplay()
}
func updateDisplay() {
var s: String = ""
if listIDs.isEmpty {
s = "No entries in listIDs"
} else {
listIDs.forEach { item in
s += "Key: \(item.key)\t\tValue: \(item.value)\n"
}
}
displayTextView.text = s
}
#objc func addEntry(_ sender: Any?) {
// add a new entry
let n: Int = listIDs.count + 1
let v: Int = Int.random(in: 1...20000)
listIDs[n] = v
// save to UserDefaults
UserDefaults.standard.saveIntDictionary(key: "cartKeys", intDictionary: listIDs)
updateDisplay()
}
#objc func reset(_ sender: Any?) {
// clear the dictionary
listIDs = [:]
// save to UserDefaults
UserDefaults.standard.removeObject(forKey: "cartKeys")
//UserDefaults.standard.saveIntDictionary(key: "cartKeysA", intDictionary: listIDs)
updateDisplay()
}
}
When run, it will look like this. Each tap of "Add a new ID" will add a new sequential entry to the dictionary (with a random value) and save to UserDefaults. Quit the app and re-run it to see the dictionary loaded. Tap "Reset" to clear it:
A couple notes:
1 - Learn about naming conventions... listIDs instead of ListIds for example.
2 - Saving "data" this way is generally not a good idea -- UserDefaults is much better suited to storing things like "app settings" for example. If your dictionary of "IDs" may grow large, you probably want to look at other data persistence methods.

I'm working with counting table and have some problem. How to fix 'Fatal error: String index is out of bounds'

I'm working with counting label String. When I run my project all my text shows and at the end it crashes with:
'Fatal error: String index is out of bounds'
on the line:
startText += String(endText[index])
in the handleUpdate method.
I don't understand why.
class AboutViewController: BaseListController {
let countingLabel: UILabel = {
let label = UILabel()
label.textColor = .white
label.textAlignment = .center
label.font = UIFont.boldSystemFont(ofSize: 18)
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(countingLabel)
countingLabel.frame = view.frame
let displayLink = CADisplayLink(target: self, selector: #selector(handleUpdate))
displayLink.add(to: .main, forMode: .default)
}
var startText = " "
let endText = "Hey! I need your help..."
var startValue = 0
#objc func handleUpdate(){
let endTextValue = endText.count - 1
let index = endText.index(endText.startIndex, offsetBy: startValue)
self.countingLabel.text = "\(startText)"
// Error on the following line:
startText += String(endText[index])
startValue += 1
if startValue > endTextValue{
startText = endText
}
print(endTextValue)
}
let animationStartDate = Date()
}
You are calling handleUpdate on a CADisplayLink, it will continue to be called after startValue has been incremented beyond the length of the string. You do have a check for startValue > endTextValue but this is after you have already tried to index using startValue, so you get a crash.
You need to remove the CADisplayLink handler once its job is done, which means you need to keep a reference to it.
var startText = ""
let endText = "Hey! I need your help..."
var startValue = 0
var displayLink: CADisplayLink?
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(countingLabel)
countingLabel.frame = view.frame
self.displayLink = CADisplayLink(target: self, selector: #selector(handleUpdate))
self.displayLink!.add(to: .main, forMode: .default)
}
#objc func handleUpdate(){
guard startValue < endText.count else {
self.displayLink?.invalidate()
self.displayLink = nil
return
}
let index = endText.index(endText.startIndex, offsetBy: startValue)
startText += String(endText[index])
self.countingLabel.text = "\(startText)"
startValue += 1
let animationStartDate = Date()
}

How to detect if UI Label was tapped?

I'm trying to make a choose-your-own adventure game that changes the text of two labels (the user choices) depending on which label the user taps. I figured I would just do a very nested if-else statement rather than bother with trying to implement a binary tree. I know how to attach the gesture recognizer to a label (I think):
let tapped1 = UITapGestureRecognizer(target: self, action: #selector(VCGame.usrChose1))
choice1.isUserInteractionEnabled = true
choice1.addGestureRecognizer(tapped1)
let tapped2 = UITapGestureRecognizer(target: self, action: #selector(VCGame.usrChose2))
choice2.isUserInteractionEnabled = true
choice2.addGestureRecognizer(tapped2)
and I can define what to do when the label is touched in the usrChose1 and usrChose2 functions, however, those functions only work once: the first time the function is chosen and my game has more than just one choice. From there, the labels will just do the same thing if the user touches them.
How would I go about having a condition inside the if-else statement that evaluates to true or false if label1 or label2 is tapped?
Here's the code for usrChoice1 and usrChoice2, for clarification
func usrChose1(sender : UITapGestureRecognizer) {
print("tap 1 working")
choice1.text = "choice1.1"
choice2.text = "choice1.2"
}
func usrChose2(sender : UITapGestureRecognizer) {
print("tap2 working")
choice1.text = "update2.1";
choice2.text = "update2.2"
}
Below image shows my requirement :
According to your requirement, I have tried the following:
I have made a dummy project with two labels inside a view controller
ViewController.swift
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var choice1Label: UILabel!
#IBOutlet weak var choiceLabel2: UILabel!
var tapStart: Bool = false
var levelType1: Level?
var levelType2: Level?
override func viewDidLoad() {
super.viewDidLoad()
let tapped1 = UITapGestureRecognizer(target: self, action: #selector(usrChose1))
choice1Label.isUserInteractionEnabled = true
choice1Label.addGestureRecognizer(tapped1)
let tapped2 = UITapGestureRecognizer(target: self, action: #selector(usrChose2))
choiceLabel2.isUserInteractionEnabled = true
choiceLabel2.addGestureRecognizer(tapped2)
setup()
}
var currentLevel1: Level?
var currentLevel2: Level?
func setup() {
let lb2Child1Child1 = Level(text: "2.1.1", subLevels: nil)
let lb2Child1Child2 = Level(text: "2.1.2", subLevels: nil)
let lb1Child1Child1 = Level(text: "1.1.1", subLevels: nil)
let lb1Child1Child2 = Level(text: "1.1.2", subLevels: nil)
let lb1Child2Child1 = Level(text: "1.2.1", subLevels: nil)
let lb1Child2Child2 = Level(text: "1.2.2", subLevels: nil)
let lb1Child1 = Level(text: "1.1", subLevels: [lb1Child1Child1, lb1Child1Child2])
let lb1Child2 = Level(text: "1.2", subLevels: [lb1Child2Child1, lb1Child2Child2])
let lb2Child1 = Level(text: "2.1", subLevels: [lb2Child1Child1, lb2Child1Child2])
let lb2Child2 = Level(text: "2.2", subLevels: nil)
levelType1 = Level(text: "1", subLevels: [lb1Child1, lb1Child2])
levelType2 = Level(text: "2", subLevels: [lb2Child1, lb2Child2])
choice1Label.text = levelType1!.text ?? ""
choiceLabel2.text = levelType2!.text ?? ""
}
func usrChose1(sender : UITapGestureRecognizer) {
if !tapStart {
currentLevel1 = levelType1
tapStart = true
}
if let subLevelsArray = currentLevel1?.subLevels {
print(subLevelsArray[0].text ?? "")
print(subLevelsArray[1].text ?? "")
choice1Label.text = subLevelsArray[0].text ?? ""
choiceLabel2.text = subLevelsArray[1].text ?? ""
currentLevel1 = subLevelsArray[0]
currentLevel2 = subLevelsArray[1]
}
}
func usrChose2(sender : UITapGestureRecognizer) {
//print("tap2 working")
// choice1Label.text = "update2.1";
//choiceLabel2.text = "update2.2"
if !tapStart {
currentLevel2 = levelType2
tapStart = true
}
if let subLevelsArray = currentLevel2?.subLevels {
print(subLevelsArray[0].text ?? "")
print(subLevelsArray[1].text ?? "")
choice1Label.text = subLevelsArray[0].text ?? ""
choiceLabel2.text = subLevelsArray[1].text ?? ""
currentLevel1 = subLevelsArray[0]
currentLevel2 = subLevelsArray[1]
}
}
}
I have made a class named Level to represent a single level and each level contains sublevels
Level.swift
import UIKit
class Level {
var text: String?
var subLevels: [Level]?
init(text: String, subLevels: [Level]?) {
self.text = text
self.subLevels = subLevels ?? nil
}
}
You have to add UITapGestureRecognizer in UILabel or UIView whatever is container.
Add 2 different Int variables in each functions usrChose1 and usrChose2 respectively, which will be work as a counter.
var i = 0
var j = 0
func usrChose1(_ recognizer: UITapGestureRecognizer) {
i++
print("Total clicked label 1 :::",i)
}
func usrChose2(_ recognizer: UITapGestureRecognizer) {
j++
print("Total clicked label 2 :::",j)
}

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.

Make Clickable UILabel Using Swift

I want to Set Particular Word clickable in UILabel text using Swift.
Is it possible?
If more than one label is here how can I detect which word is pressed?
You can not do with the simple label.
There is library available in the github.
https://github.com/TTTAttributedLabel/TTTAttributedLabel
From this you can use the method called yourLabel.addLinkToURL()
class ViewController: UIViewController , TTTAttributedLabelDelegate{
#IBOutlet var lbl: TTTAttributedLabel!
override func viewDidLoad() {
super.viewDidLoad()
var str : NSString = "Hello this is link"
lbl.delegate = self
lbl.text = str as String
var range : NSRange = str.rangeOfString("link")
lbl.addLinkToURL(NSURL(string: "http://github.com/mattt/")!, withRange: range)
}
func attributedLabel(label: TTTAttributedLabel!, didSelectLinkWithURL url: NSURL!) {
UIApplication.sharedApplication().openURL(url)
}
}
SWIFT 3.0
privacyLabel.delegate = self
let strPolicy : NSString = "Agree to the Terms & Conditions"
privacyLabel.text = strPolicy as String
let range1 : NSRange = strPolicy.range(of: "Terms & Conditions")
privacyLabel.addLink(to: URL(string: "http://Terms.com")!, with: range1)
func attributedLabel(_ label: TTTAttributedLabel!, didSelectLinkWith url: URL!) {
print("url \(url)")
// UIApplication.sharedApplication().openURL(url)
}
I'd like to share my library https://github.com/psharanda/Atributika
It contains modern replacement of TTTAtributedLabel + powerful set of methods to detect and style different stuff like tags, hashtags, mentions etc (everything of that can be clickable)
Some code to show how it works:
let link = Style
.font(.boldSystemFont(ofSize: 14))
.foregroundColor(.black)
.foregroundColor(.red, .highlighted)
let tos = link.named("tos")
let pp = link.named("pp")
let all = Style
.font(.systemFont(ofSize: 14))
.foregroundColor(.gray)
let text = "<tos>Terms of Service</tos> and <pp>Privacy Policy</pp>"
.style(tags: tos, pp)
.styleAll(all)
let tosLabel = AttributedLabel()
tosLabel.textAlignment = .center
tosLabel.attributedText = text
tosLabel.onClick = { label, detection in
switch detection.type {
case .tag(let tag):
switch tag.name {
case "pp":
print("Privacy Policy clicked")
case "tos":
print("Terms of Service clicked")
default:
break
}
default:
break
}
}
view.addSubview(tosLabel)

Resources