iOS Xcode Swift Combining Input FirstName and LastName into a FullName Issue - ios

I am having trouble combining a first and last name for this code I am running to update it to a tableviewcell. It seems as if it is not saving either first or last name and merely replacing it as I type new text in. I am not sure what is going on and I am certain the row numbers that I am using in my .plist match with the code. Any help with this or other alternatives are appreciated.
func textfieldTextWasChanged(newText: String, parentCell: CustomCell) {
let parentCellIndexPath = tblExpandable.indexPathForCell(parentCell)
let currentFullname = cellDescriptors[0][12]["primaryTitle"] as! String
let fullnameParts = currentFullname.componentsSeparatedByString(" ")
var newFullname = ""
if parentCellIndexPath?.row == 13 {
if fullnameParts.count == 2 {
newFullname = "\(newText) \(fullnameParts[1])"
}
else {
newFullname = newText
}
}
else {
newFullname = "\(fullnameParts[0]) \(newText)"
}
cellDescriptors[0][12].setValue(newFullname, forKey: "primaryTitle")
tblExpandable.reloadData()
}

What most likely is happening is that when you're calling tblExpandable.reloadData(), cellForRowAtIndexPath is getting called, and it's overwriting your changes that you're making here. You either need to do some cell caching or possibly consider using a UIScrollView instead of a UITableView.

Related

Couchbase lite, Search query taking very long time

When I try to search the couchbase documents of size around 10K, the searching is taking very long time. Below are the code snippet. Can anyone optimize it or suggest me any alternative approach. Thank you.
1) Search function
func search(keyword:String) -> [[String:AnyObject]] {
var results:[[String:AnyObject]]=[]
let searchView = database.viewNamed(AppConstants().SEARCH)
if searchView.mapBlock == nil {
startIndexing()
}
let query = searchView.createQuery()
var docIds = Set<String>()
let result = try query.run()
while let row = result.nextRow() {
let key = "\(row.key)"
let keyArr = keyword.characters.split(" ")
for (index, element) in keyArr.enumerate() {
let keyItem = String(element)
if key.lowercaseString.containsString(keyItem.lowercaseString) {
let value = row.value as! [String:AnyObject]
let id = value["_id"] as? String
if id != nil && !docIds.contains(id!) {
results.append(value)
docIds.insert(id!)
}
}
}
}
}
2) Indexing
func startIndexing() {
let searchView = database.viewNamed(AppConstants().SEARCH)
if searchView.mapBlock == nil {
searchView.setMapBlock({ (doc, emit) in
let docType = doc[AppConstants().DOC_TYPE] as! String
if AppConstants().DOC_TYPE_CONTACT.isEqual(docType) {
self.parseJsonToKeyValues(doc)
for value in self.fields.values {
emit(value, doc)
}
self.fields.removeAll()
}
}, version: "1")
}
}
self.parseJsonToKeyValues(doc) will return me the key value store of my documents to index.
You're emitting the entire document along with every field for your view. This could easily cause your queries to be slow. It also seems unlikely you want to do this, unless you really need to be able to query against every field in your document.
It's considered best practice to set your map function right after opening the database. Waiting until right before you query may or may not slow you down.
See https://developer.couchbase.com/documentation/mobile/current/guides/couchbase-lite/native-api/view/index.html for more, especially the section labeled "Development Considerations".

Trying to add filter to searchBar for a collection view populated with type AnyObject

I'm sorry about the title. I have a collectionView populated with an array of objects of type (AnyObject). I'm trying to add search to this. I found a tutorial on it but in the tutorial it is just an array of Strings. I want the searchbar to search based on username. I got everything working except this function:
func filterContentForSearchText(searchText:String) {
self.friendsArrayForSearchResult = self.friendsArray.filter() {
guard let type = ($0 as AnyObject)["username"] as? String else {
return false
}
return type.rangeOfString("username") != nil
}
}
Basically if the user is searching, the collectionview is being populated with self.friendsArrayForSearchResult and if the user isn't searching it is populated with self.friendsArray.
Okay so I got it working with this:
self.usersArrayForSearchResult = self.usersArray.filter() {
if let pos = ($0["username"] as! String).lowercaseString.rangeOfString(searchText.lowercaseString) {
return (pos.startIndex == ($0["username"] as! String).startIndex)
}
return false
}
But the only thing is I want it to show users who contain what the user is searching for. So if their name is fred and you type ed then fred comes up...is this possible using this function or do I have to do a bunch of other stuff?
Okay so after being up all night trying to figure this out...apparently this was all I needed to do.
self.friendsArrayForSearchResult = self.friendsArray.filter() {
if ($0["username"] as! String).lowercaseString.containsString(searchText.lowercaseString) {
return true
}
return false
}

how to make retrieve button for previous Value

can someone help me
i make button to retrieve previous Values
but i have two TextFiled
i must write in two TextFiled for work retrieve button
i do not want this happens
i want when I write in the first TextFiled, retrieve button work without any problem
but if i write in first TextFiled and second TextFiled at the same time i want retrieve button work without any problem
var previousValues: [String] = [String]();
var previousValues1: [String] = [String]();
previousValues.append(TextFailde.text ?? "error");
previousValues1.append(TextFilde1.text ?? "error");
if self.previousValues.count > 0 {
let previousValue = self.previousValues.removeLast()
let subtracted = (Int(self.lblZeroUs.text!)!) - (Int(previousValue)!)
self.lblZeroUs.text = "\(subtracted)"
}
else if self.previousValues1.count > 0 {
let previousValue = self.previousValues1.removeLast()
let subtracted2 = (Int(self.lblZeroThey.text!)!) - (Int(previousValue)!)
self.lblZeroThey.text = "\(subtracted2)"
}
and here the error
There are many errors, first of all you dont declare your properties with the first letter in uppercase, it's considered a bad practice.
Then, when you involve your properties in mathematical operations what do you need is to assign them a start value, especially if your code try to convert strings.
In Swift, you don’t need to write semicolons at the end of every statement.
I dont know the rest of your code, but your lines crash because you attempt to run mathematical operations using properties have nil as value.
This below it's just an example to avoid the first crashing for nil:
textFailde.text = "0"
textFilde1.text = "0"
previousValues.append(textFailde.text ?? String(0))
previousValues1.append(textFilde1.text ?? String(0))
self.lblZeroUs.text = String(0)
self.lblZeroThey.text = String(0)
if self.previousValues.count > 0 {
let subtracted = (Int(self.lblZeroUs.text!)!) - (Int(self.previousValues.last!))!
self.previousValues.removeLast()
self.lblZeroUs.text = "\(subtracted)"
}
else if self.previousValues1.count > 0 {
let subtracted2 = (Int(self.lblZeroThey.text!)!) - (Int(self.previousValues1.last!))!
self.previousValues1.removeLast()
self.lblZeroThey.text = "\(subtracted2)"
}
previousValues.append(TextFailde.text ?? "error");
previousValues.append(TextFilde1.text ?? "error");
You added to the same array twice, try changing the code to
previousValues.append(TextFailde.text ?? "error");
previousValues1.append(TextFilde1.text ?? "error");

Replace part of string with lower case letters - Swift

I have a Swift based iOS app and one of the features allows you to comment on a post. Anyway, users can add "#mentions" in their posts to tag other people. However I want to stop the user from adding a username with a capital letter.
Is there anyway I can convert a string, so that the #usernames are all in lowercase?
For example:
I really enjoy sightseeing with #uSerABC (not allowed)
I really enjoy sightseeing with #userabc (allowed)
I know there is a property for the string in swift called .lowercaseString - but the problem with that, is that it makes the entire string lowercase and thats not what I want. I only want the #username to be in lower case.
Is there any way around this with having to use the .lowercase property.
Thanks for your time, Dan.
This comes from a code I use to detect hashtags, I've modified to detect mentions:
func detectMentionsInText(text: String) -> [NSRange]? {
let mentionsDetector = try? NSRegularExpression(pattern: "#(\\w+)", options: NSRegularExpressionOptions.CaseInsensitive)
let results = mentionsDetector?.matchesInString(text, options: NSMatchingOptions.WithoutAnchoringBounds, range: NSMakeRange(0, text.utf16.count)).map { $0 }
return results?.map{$0.rangeAtIndex(0)}
}
It detects all the mentions in a string by using a regex and returns an NSRange array, by using a range you have the beginning and the end of the "mention" and you can easily replace them with a lower case version.
Split the string into two using the following command -
let arr = myString.componentsSeparatedByString("#")
//Convert arr[1] to lower case
//Append to arr[0]
//Enjoy
Thanks to everyone for their help. In the end I couldn't get any of the solutions to work and after a lot of testing, I came up with this solution:
func correctStringWithUsernames(inputString: String, completion: (correctString: String) -> Void) {
// Create the final string and get all
// the seperate strings from the data.
var finalString: String!
var commentSegments: NSArray!
commentSegments = inputString.componentsSeparatedByString(" ")
if (commentSegments.count > 0) {
for (var loop = 0; loop < commentSegments.count; loop++) {
// Check the username to ensure that there
// are no capital letters in the string.
let currentString = commentSegments[loop] as! String
let capitalLetterRegEx = ".*[A-Z]+.*"
let textData = NSPredicate(format:"SELF MATCHES %#", capitalLetterRegEx)
let capitalResult = textData.evaluateWithObject(currentString)
// Check if the current loop string
// is a #user mention string or not.
if (currentString.containsString("#")) {
// If we are in the first loop then set the
// string otherwise concatenate the string.
if (loop == 0) {
if (capitalResult == true) {
// The username contains capital letters
// so change it to a lower case version.
finalString = currentString.lowercaseString
}
else {
// The username does not contain capital letters.
finalString = currentString
}
}
else {
if (capitalResult == true) {
// The username contains capital letters
// so change it to a lower case version.
finalString = "\(finalString) \(currentString.lowercaseString)"
}
else {
// The username does not contain capital letters.
finalString = "\(finalString) \(currentString)"
}
}
}
else {
// The current string is NOT a #user mention
// so simply set or concatenate the finalString.
if (loop == 0) {
finalString = currentString
}
else {
finalString = "\(finalString) \(currentString)"
}
}
}
}
else {
// No issues pass back the string.
finalString = inputString
}
// Pass back the correct username string.
completion(correctString: finalString)
}
Its certainly not the most elegant or efficient solution around but it does work. If there are any ways of improving it, please leave a comment.

Swift: Appending object inside dictionary

I'd like to add my dictionary with array in it to my arrayOfDictionary, i tried the suggested answer on this link, but it didn't work for me. I'm having problem on appending object in my dictionary.
Here's my code:
func formatADate() {
var dateFormatter = NSDateFormatter()
dateFormatter.dateStyle = NSDateFormatterStyle.LongStyle
var journalDictionary = Dictionary<String, [Journal]>()
for index in 0..<self.sortedJournal.count {
let dateString = dateFormatter.stringFromDate(self.sortedJournal[index].journalDate)
var oldDateString = ""
// Split Date
var dateStringArr = split(dateString){$0 == " "}
var newDateString = "\(dateStringArr[0]) \(dateStringArr[2])"
// Append journal to corresponding dates
// journalDictionary[newDateString]? += [self.sortedJournal[index]]
// journalDictionary[newDateString]!.append(self.sortedJournal[index])
journalDictionary[newDateString]?.append(self.sortedJournal[index])
// add to array of journal
if !(newDateString == oldDateString) || (oldDateString == "") {
arrayOfJournalDictionary.append(journalDictionary)
}
}
println(arrayOfJournalDictionary)
}
With this line of code, it gives me empty object.
journalDictionary[newDateString]?.append(self.sortedJournal[index])
Any suggestion on how I can accomplish/fix this? I'm pretty amateur in Swift, so any help would be appreciated! Thank you.
Woah, date magic with string splits and stuff, yeiks. You already are using NSDateFormatters, for the wrong reasons though. Since journalDate is a date, use the formatter to give you the exact string you want from that date, dont let it give you some generic string and split and concatenate and argh... NOBODY will understand what you are trying to do there.
Back to the question:
Your journalDictionary is empty, if you write
journalDictionary[newDateString]?.append(self.sortedJournal[index])
You tell the program to read at "index" newDateString and if there is something take that and append a new value to it.
Do you see the mistake already?
if there is something -> You have no logic yet to insert the initial empty [Journal] for any given key.
At some point in your code you have to set up the array like so:
journalDictionary["myKey"] = []
Or probably more likely:
if journalDictionary[newDateString] == nil {
journalDictionary[newDateString] = [self.sortedJournal[index]]
} else {
journalDictionary[newDateString]?.append(self.sortedJournal[index])
}

Resources