String indices in Swift 2 - xcode

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
}

Related

Eureka forms gives error EXC_BAD_INSTRUCTION INVOP

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.

Cocoa Not Calling ViewController Function

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.

addAttribute fails in Swift 1.2 (Xcode 6.3)

This was working before upgrading to Swift 1.2 and Xcode 6.3.
var mutString : NSMutableAttributedString = NSMutableAttributedString(string: "K2")
mutString.addAttribute(kCTSuperscriptAttributeName, value:-1, range:NSMakeRange(1, 1))
var result : String = mutString.string
The result should contain the string K2 (with "2" as a subscript).
But now I get this error:
Cannot invoke addAttribute with an argument list of type '(CFString!, value:Int, range:NSRange)'
Please point me to the right solution/documentation.
Just add "as! String" after the kCTSuperscriptAttributeName
addAttribute accepts an argument list of type (String, value: AnyObject, range: NSRange). The latter two seem to be fine, but you can't use a CFString! with this method.
You have to use the native Swift String type in Swift 1.2 (which marks a further departure from its Objective-C heritage). Changing kCTSuperscriptAttributeName's type to String should solve the issue.

ABRecordCopyValue not working when object doesn't exist

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.

how to read parameters from console to method in groovy?

I am new to groovy.I am reading values for 2 variables from console with below lines of code.
System.in.withReader {
println "Version: "
version = it.readLine()
println "Doc Type:"
Doc=it.readLine()
call getBillID(version,Doc)
}
getBillid method is as below,
def getBillID(int version,int doc)
{
allNodes.BillID.each {
theregularExpression=/\d+_\d+_\d+_\d_\d+_\d+_\d_${version}_${Doc}_\d+_\d+/
if(it != "" && it =~ theregularExpression) {
println "******" + it
}
}
}
now i want to use those variable values in my getBILLID method but i am getting error as
No signature of method: ReadXML.getBillID() is applicable for argument types: (java.lang.String, java.lang.String) values: [9, ]
where i went wrong.can any one tell me plz..
In addition to #Kalarani's answer, you could also do this:
System.in.withReader {
print "Version: "
int version = it.readLine() as int
print "Doc Type: "
int doc = it.readLine() as int
getBillID( version, doc )
}
As an aside; I would be careful with your capitalisation and variable names, ie: you have a variable called Doc with a capital letter. This is not the standard naming scheme, and you are best using all lowercase for variable names. You can see where it has got confused in the getBillID method. The parameter is called doc (all lowercase), but in the regular expression you reference ${Doc} (uppercase again).
This sort of thing is going to end up causing you a world of pain and bugs that might take you longer to find
Where is the getBillId() method defined? and what is the signature of the method? It would help understanding your problem if you could post that.

Resources