I built a viewcontroller with a combobox that has the completion option so that when I type a letter, it finds the first occurence in the list starting with that letter. It works fine. I then copied the code to another view controller and changed the appropriate source information. It doesn't work. I've been comparing the two for a couple days now to see if I missed anything and it all seems OK. I've put in a number of print statements to isolate the problem. This is the console log of a run through both of controllers:
// 1
completed string starting. Tag: 1
// 2
Starting findFirstOccurrence parm string: m
findFirstOccurrence dataRow: ["style_id": 61, "name": Ma (She's Making Eyes at Me), "id": 1040, "year_written": <null>, "year_published": <null>, "notes": <null>]
findFirstOccurrence returning: Ma (She's Making Eyes at Me)
objectValueForItemAt index: 1637
entry: Ma (She's Making Eyes at Me)
// 3
Entered textShouldEndEditing - tag: 1 selectedRow: 1637
// 4
initializeDialog creditRow: ["record_id": 485]
completed string starting. Tag: 1
// 5
Starting findFirstOccurrence parm string: m
findFirstOccurrence dataRow: ["other_instruments": <null>, "name": Maucha Adnet, "last_name": Adnet, "primary_instrument": vocals, "id": 2368, "first_name": Maucha, "birth_year": <null>, "death_year": <null>, "notes": <null>]
findFirstOccurrence returning: Maucha Adnet
// 6
Entered textShouldEndEditing - tag: 1 selectedRow: -1
I activate the controller. The cursor appears in the first field, which is the working combobox
I type the letter m. My findFristOccurance method is called. It returns the string shown. Then my objectValueForItemAt is called. It returns the entry shown.
I hit the tab key. My textShouldEndEditing is called and it's happy and returns a valid response. The cursor moves to the next field.
I exit the view controller - it's a modal dialog - and enter the one that doesn't work. The cursor appears in the first field, which is the non-working combobox.
I type the letter m. My findFristOccurance method is called. It returns the string shown. My objectValueForItemAt is NOT called.
When I tab out of the field and textShouldEndEditing is called, it return invalid because there is not selection, i.e., -1.
I know the objectValueForItemAt is OK in the problem controller because it is called repeatedly when I click on the down arrow on the combobox to show the entries.
The problem appears to be that objectValueForItemAt is not being called in the problem controller. I've compared both comboboxes in the story board. They are both set the same. Is there some setting I'm missing somewhere?
This is last function called in both controllers before they diverge. This version is from the problem controller:
func comboBox(_ aComboBox: NSComboBox, completedString string: String) -> String? {
print("completed string starting. Tag: ", aComboBox.tag)
var returnString = ""
switch aComboBox.tag {
case artistTableTag:
returnString = findFirstOccurrence(table: artists.table, string: string)
default:
break
}
return returnString
}
func findFirstOccurrence(table: [[String: Any]], string: String) -> String {
print("Starting findFirstOccurrence parm string: ", string)
var returnString = ""
for var dataRow in table {
let dataString = dataRow["name"] as! String
if dataString.commonPrefix(with: string,
options: String.CompareOptions.caseInsensitive).lengthOfBytes(using: String.Encoding.utf8) ==
string.lengthOfBytes(using: String.Encoding.utf8) {
print("findFirstOccurrence dataRow: ", dataRow)
returnString = dataRow["name"] as! String
break
}
}
print("findFirstOccurrence returning: ", returnString)
return returnString
}
In case you're wondering about the switch statement with only one entry, the source controller has five and choose to keep consistent.
Found it. I had:
func comboBox(aComboBox: NSComboBox, indexOfItemWithStringValue string: String) -> Int {
instead of the correct:
func comboBox(_ aComboBox: NSComboBox, indexOfItemWithStringValue string: String) -> Int {
I've had this problem several times when copying tutorial or stackoverflow answers prior to Swift 3.0. Xcode catches a lot of out of date usage, but not this type. If your functions are not being called, check for this. I hadn't had the problem in awhile and got complacent.
Related
I have the following code
if editingStyle == .delete{
let refreshAlert = UIAlertController(title: "Delete Collection", message: "All expenses in this collection will also be lost.", preferredStyle: UIAlertControllerStyle.alert)
refreshAlert.addAction(UIAlertAction(title: "Ok", style: .default, handler: { (action: UIAlertAction!) in
let collection = self.collections[indexPath.row]
CoreDataHelper.deleteCollection(collection: collection)
for expense in self.collectionExpensesDelete{
print ("deleted")
if expense.collection! == self.collections[indexPath.row].title{
CoreDataHelper.deleteExpense(expense: expense)
}
}
self.collections.remove(at: indexPath.row)
self.collections = CoreDataHelper.retrieveCollections()
}))
What I want to do is to delete all expenses associated if a collection is deleted. However the for loop in the middle, the breakpoint that I have placed on it doesn't get called. Only the initial breakpoint on the "for" statement gets called and none of the code inside get called, including the delete statement.
Can anyone tell me what I am doing wrong?
There is no reason as to the code you posted above that the for loop should not be executed.
There is a potential issue with expense.collection! in your if statement being force unwrapped. Is this intentional? If so why are you not guard let of if let this. I could well explain why your code inside the if statement is not being executed.
What is CoreDataHelper? If it is a custom class to help manage interactions with CoreData then make sure you have properly implemented the context.delete(object) correctly in your CoreDataHelper class.
In the CoreDataHelper you should be something like this:
Fetch the record that needs to be deleted
Mark the record for deletion
Save the changes
I have just started using Eureka Forms in my Swift 3 project.
I have created my first form with a TextRow that looks like this:
<<< TextRow() {
$0.tag = tagname
$0.title = title
$0.placeholder = placeholder
}
It displays correctly on the simulator, however when I click in the field I immediately get a crash:
EXC_BAD_INSTRUCTION (code =EXC_1386,INVOP,subcode=0x0)
On the guard line (from the Eureka framework):
private func displayValue(useFormatter: Bool) -> String? {
guard let v = row.value else { return nil }
It must be something simple, can anybody point me in the right direction please?
That error seems to say that the row.value is needed, so maybe you can add an initial value ("") in the init callback. It may be an old or unreleased commit. Please try the latest version or see if the version you used has that particular bug.
Below is my code for the current search, right now it only checks string by string. How do I implement ngram into it? This code checks an array of strings compared to what the user types in on the front end. It generates results with that string.
ngram is a solution i found online for what i need. However, what i want is the ability for users to search in the array without the use of spaces, say the array is "I love sushi and popcorn,...." and the user searches "I love popcorn" the array which consist of the string "I love sushi and popcorn" will not show up. However, I want it to be.
One option is to write a function that puts each string seperated by space into another array and have the search function run through a loop in that array and do this for each other strings. However, I find this inefficient.
Please let me know if there are other solutions. Thanks
func updateSearchResults(for searchController: UISearchController) {
// filter results
// reload table
let searchString:String = searchController.searchBar.text!
self.dataToDisplay = self.sampleData.filter({ (dataString:String) -> Bool in
let match = dataString.range(of: searchString, options: NSString.CompareOptions.caseInsensitive)
if match != nil {
return true
}
else {
return false
}
})
self.pdfArrSearch = self.pdfArr.filter({ (dataString:String) -> Bool in
let match = dataString.range(of: searchString, options: NSString.CompareOptions.caseInsensitive)
if match != nil {
return true
}
else {
return false
}
})
I decided to learn Swift and I decided to start with Swift 2 right away.
So here is a very basic example that's similar to one of the examples from Apple's own e-book about Swift
let greeting = "Guten Tag"
for index in indices(greeting) {
print(greeting[index])
}
I tried this in the playground of Xcode 7 and I received the following error
Cannot invoke 'indices' with an argument list of type '(String)'
I also tried the same thing with Xcode 6 (which is Swift 1.2 AFAIK) and it worked as expected.
Now, my question is: Is this
An error in Xcode 7, it's still a beta release after all, or
Something that just doesn't work anymore with Swift 2 and the e-book just isn't fully updated yet?
Also: If the answer is "2", how would you replace indices(String) in Swift 2?
In a Playground, if you go to menu View > Debug Area > Show debug area, you can see the full error in the console:
/var/folders/2q/1tmskxd92m94__097w5kgxbr0000gn/T/./lldb/94138/playground29.swift:5:14: error: 'indices' is unavailable: access the 'indices' property on the collection
for index in indices(greeting)
Also, Strings do not conform to SequenceTypes anymore, but you can access their elements by calling characters.
So the solution for Swift 2 is to do it like this:
let greeting = "Guten Tag"
for index in greeting.characters.indices {
print(greeting[index])
}
Result:
G
u
t
e
n
T
a
g
Of course, I assume your example is just to test indices, but otherwise you could just do:
for letter in greeting.characters {
print(letter)
}
Just for completion, I have found a very simple way to get characters and substrings out of strings (this is not my code, but I can't remember where I got it from):
include this String extension in your project:
extension String {
subscript (i: Int) -> Character {
return self[self.startIndex.advancedBy(i)]
}
subscript (i: Int) -> String {
return String(self[i] as Character)
}
subscript (r: Range<Int>) -> String {
return substringWithRange(Range(start: startIndex.advancedBy(r.startIndex), end: startIndex.advancedBy(r.endIndex)))
}
}
this will enable you to do:
print("myTest"[3]) //the result is "e"
print("myTest"[1...3]) //the result is "yTe"
Here is the code that you looking:
var middleName :String? = "some thing"
for index in (middleName?.characters.indices)! {
// do some thing with index
}
This line of code in Swift causes me problems when the address book has a contact with no last name.
I've tried to resolve it a number of ways to no avail. Is there some sort of try catch statement or error handling I can use? Or check if AnyObject is null (the return type of
ABRecordCopyValue(person, kABPersonLastNameProperty).takeRetainedValue()).
I've tried using optional types but it doesn't seem to work since the app stops running the moment you select a contact with no last name - and the line of code below gets highlighted with the error Thread
1: EXC_BAD_ACCESS
let lName = ABRecordCopyValue(person, kABPersonLastNameProperty).takeRetainedValue() as String
ABRecordCopyValue can actually return nil so you should unwrap it. Also, casting to String didn't work for me so I'm using NSString.
if let firstName = ABRecordCopyValue(abContact, kABPersonFirstNameProperty)?.takeRetainedValue() as? NSString {
println("FIRST NAME: \(firstName)")
}
else {
println("No Name")
}
Another thing you could try is instead of getting the first and lastName individually, you could also try to get the composed name.
if let fullName = ABRecordCopyCompositeName(abContact)?.takeRetainedValue() as String? {
println("Full Name: \(fullName)")
}
P.S: I've also tried all the answers from this question but despite of making perfect sense and working when debugging the app, they crashed when I deployed the archive directly into the phone.