2014-09-07 25 views
5

Tôi có một ứng dụng được viết bằng Swift đang kéo người liên hệ của người dùng từ sổ địa chỉ của họ.Mảng lọc Swift sử dụng NSPredicate

Tôi muốn lọc ra sự tiếp xúc chỉ chứa tên công ty (để bạn có được của bạn "giả định" người thật xúc và không phải doanh nghiệp)

Sau đây là cách này đang được thực hiện trong phiên bản Objective-C các ứng dụng của tôi:

NSArray *allContacts = (__bridge_transfer NSArray *)ABAddressBookCopyArrayOfAllPeople(addressBook); 

NSPredicate *predicate = [NSPredicate predicateWithBlock:^BOOL(id person, NSDictionary *bindings) { 
    NSString *firstName = CFBridgingRelease(ABRecordCopyValue((__bridge ABRecordRef)person, kABPersonFirstNameProperty)); 
    NSString *lastName = CFBridgingRelease(ABRecordCopyValue((__bridge ABRecordRef)person, kABPersonLastNameProperty)); 

    return (firstName || lastName); 
}]; 

NSArray *peopleNotCompanies = [allContacts filteredArrayUsingPredicate:predicate]; 

này hoạt động hoàn hảo, vì vậy đây là nỗ lực của tôi để làm điều này trong Swift:

var contactList: NSArray = ABAddressBookCopyArrayOfAllPeople(addressBook).takeRetainedValue() 

var predicate: NSPredicate = NSPredicate { (AnyObject person, NSDictionary bindings) -> Bool in 
    var firstName: String = ABRecordCopyValue(person as ABRecordRef, kABPersonFirstNameProperty).takeRetainedValue() as String 
    var lastName: String = ABRecordCopyValue(person as ABRecordRef, kABPersonLastNameProperty).takeRetainedValue() as String 

    return firstName || lastName 
}) 

Bây giờ này có một vài vấn đề. Tôi nhận được những lỗi trên báo cáo kết quả lợi nhuận và kết thúc cuộc gọi vị:

Error Messages

Làm thế nào tôi có thể cung cấp chức năng tương tự như tìm thấy trong mã ObjC tôi trong Swift? Hoặc là có một cách tốt hơn trong nhanh chóng để kiểm tra xem một số liên lạc có chỉ một tên công ty và sau đó bỏ qua nó từ mảng cuối cùng?

Cảm ơn!

Trả lời

5

Nếu bạn có firstname và lastname có dây tùy chọn, bạn có thể so sánh chúng với con số không và sử dụng chúng trong một biểu thức boolean.

Lỗi thứ hai của bạn là do thêm paren sau khi đóng. Mã này sẽ hoạt động.

var predicate: NSPredicate = NSPredicate { (AnyObject person, NSDictionary bindings) -> Bool in 
    var firstName: String? = ABRecordCopyValue(person as ABRecordRef, kABPersonFirstNameProperty).takeRetainedValue() as? String 
    var lastName: String? = ABRecordCopyValue(person as ABRecordRef, kABPersonLastNameProperty).takeRetainedValue() as? String 

    return firstName != nil || lastName != nil 
} 
+0

Nếu bạn sử dụng NSArray thay vì Array, bạn có thể thực hiện dòng mã sau: let filtersContacts: NSArray = contactList.filteredArrayUsingPredicate (predicate) –

+0

Cảm ơn bạn đã làm rõ, phần bổ sung) đã thực sự ném tôi đi vì tôi không chú ý nó! –

0

Thử nghiệm của bạn ở dòng cuối cùng trong Mục tiêu-C sẽ trả về nếu firstName là 0 hoặc nếu lastName là 0. Trong mã nhanh chóng của bạn, bạn chỉ đang cố gắng so sánh hai chuỗi như thể chúng là Bools. Thay vào đó, bạn muốn quay trở lại nếu firstName tồn tại, vì vậy thay vào đó bạn nên làm điều này trong cả hai mục tiêu-c và mã Swift:

return firstName != nil 
+0

Dường như không hoạt động, sẽ ném một loại lỗi khác. Tôi càng nhìn vào điều này mặc dù, có vẻ như tôi đang lãng phí thời gian của tôi bởi vì Swift không có một phương thức filterArrayUsingPredicate:. Vì vậy, tôi thực sự cần phải kiểm tra mỗi ABRecordRef và xem nếu tên và họ là nil trong khi giá trị công ty không phải là, và sau đó bỏ qua rằng ABRecordRef –

+0

@KyleBegeman Swift có quyền truy cập vào tất cả các phương pháp tương tự như bạn có quyền truy cập vào mục tiêu- C bạn chỉ cần nhìn vào NSArray chứ không phải là lớp mảng gốc của Swift. Lỗi mới là gì? – davecom

4

Nếu bạn chuyển đổi NSArray thành một mảng nhanh, bạn có thể sử dụng phương thức Array.filter của Swift. Dưới đây là ví dụ với các đối tượng đơn giản hơn để rõ ràng:

let arrObjc: NSArray = ["aaa", "bab", "bbb", "baa", "cbc"] 
let arr: [AnyObject] = arrObjc //create a swift array with same data 

// filter takes a block that returns a boolean. True: keep the item, False: drop it. 
arr.filter{ 
    if let s = $0 as? String { // first try to cast AnyObject to our expected type. 
    return contains(s, "a") // return true if we want this item, false otherwise. 
    } else { 
    return false    // this object is of the wrong type, return false. 
    } 
} 

// returns: ["aaa", "bab", "baa"] 
Các vấn đề liên quan