1

Code works in Objective-C, trying to convert to Swift. I've provided the working Objective-C code and the Swift code that gives a compile error on line 10 (the for subValue in aPropertyValue ... fast enumerator. Swift error "Type 'ABMultiValue' does not conform to protocol 'SequenceType'".

Some ABPerson properties may contain multiple values (for example multiple phone numbers) and are objects of the ABMultiValue class (although Xcode debugger reports them as ABMultiValueCoreDataWrapper class). The attached Objective-C code loops through the multiple values. I am trying to do the same in Swift but can not get past the compile error. Both are Xcode Command Line projects.

The Objective-C code:

#import <Foundation/Foundation.h>
#import <AddressBook/AddressBook.h>
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
        NSArray *people = [addressBook people];
        for (ABPerson *person in people) {
            for (NSString *aProperty in [ABPerson properties]) {
                id aPropertyValue = [person valueForProperty: aProperty];
                if ([aPropertyValue isKindOfClass: [ABMultiValue class]]) {
                    for (id subValue in aPropertyValue) {
                        NSLog(@"%@",subValue);
                    }
                }
            }
        }
    }
    return 0;
}

The swift code:

import Foundation
import AddressBook
let addressBook = ABAddressBook.sharedAddressBook()
let people = addressBook.people()
for person in people {
    for property in ABPerson.properties() {
        if let aPropertyValue : AnyObject = person.valueForProperty(property as NSString) {
            if aPropertyValue is ABMultiValue {
//                for subValue in aPropertyValue {
                for subValue in aPropertyValue as ABMultiValue {
                    println("\(subValue)") 
                }
            }
        }
    }
}
Rob
  • 415,655
  • 72
  • 787
  • 1,044
VinnyC
  • 13
  • 5

1 Answers1

0

You could obviously use the index:

let addressBook = ABAddressBook.sharedAddressBook()
let people = addressBook.people()
for person in people {
    for property in ABPerson.properties() {
        if let multiValue = person.valueForProperty(property as NSString) as? ABMultiValue {
            for i in 0 ..< multiValue.count() {
                println(multiValue.valueAtIndex(i))
            }
        }
    }
}

Alternatively, as suggested in this answer, you can define an extension that conforms to SequenceType:

extension ABMultiValue: SequenceType {
    public func generate() -> NSFastGenerator {
        return NSFastGenerator(self)
    }
}

Then you can:

let addressBook = ABAddressBook.sharedAddressBook()
let people = addressBook.people()
for person in people {
    for property in ABPerson.properties() {
        if let multiValue = person.valueForProperty(property as NSString) as? ABMultiValue {
            for identifier in multiValue {
                let value: AnyObject = multiValue.valueForIdentifier(identifier as String)
                println("\(identifier) : \(value)")
            }
        }
    }
}
Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044