ใช้ Predicate ใน Swift


94

ฉันกำลังทำงานผ่านบทช่วยสอนที่นี่ (เรียนรู้ Swift) สำหรับแอปแรกของฉัน: http://www.appcoda.com/search-bar-tutorial-ios7/

ฉันติดอยู่ในส่วนนี้ (รหัส Objective-C):

- (void)filterContentForSearchText:(NSString*)searchText scope:(NSString*)scope
{
    NSPredicate *resultPredicate = [NSPredicate predicateWithFormat:@"name contains[c]         %@", searchText];
    searchResults = [recipes filteredArrayUsingPredicate:resultPredicate];
}

มีใครแนะนำวิธีสร้าง NSPredicate ใน Swift ได้บ้าง

คำตอบ:


158

นี่เป็นเพียงการสลับไวยากรณ์ ตกลงดังนั้นเราจึงเรียกวิธีนี้ว่า:

[NSPredicate predicateWithFormat:@"name contains[c] %@", searchText];

ในสวิฟท์, ก่อสร้างข้าม "blahWith ..." ส่วนหนึ่งและใช้เพียงชื่อชั้นเป็นฟังก์ชั่นและจากนั้นตรงไปที่การขัดแย้งดังนั้นก็จะกลายเป็น[NSPredicate predicateWithFormat: …] NSPredicate(format: …)(ตัวอย่างเช่น[NSArray arrayWithObject: …]จะกลายเป็นNSArray(object: …)นี่คือรูปแบบปกติใน Swift)

ตอนนี้เราแค่ส่งอาร์กิวเมนต์ไปยังตัวสร้าง ใน Objective-C ตัวอักษร NSString ดูเหมือน@""แต่ใน Swift เราใช้แค่เครื่องหมายคำพูดสำหรับสตริง นั่นทำให้เรา:

let resultPredicate = NSPredicate(format: "name contains[c] %@", searchText)

และในความเป็นจริงนั่นคือสิ่งที่เราต้องการตรงนี้

(อนึ่งคุณจะสังเกตเห็นคำตอบอื่น ๆ แทนที่จะใช้สตริงรูปแบบเช่น"name contains[c] \(searchText)"นั้นไม่ถูกต้องซึ่งใช้การแก้ไขสตริงซึ่งแตกต่างจากการจัดรูปแบบเพรดิเคตและโดยทั่วไปจะใช้ไม่ได้กับสิ่งนี้)


ขอบคุณ. คุณช่วยฉันสักวัน!
Hugo

2
ในการระบุบรรทัดที่สองของวิธีการของคุณคุณอาจใช้เพรดิเคตเป็น:searchResults = recipes.filter { resultPredicate.evaluateWithObject($0) }
Ben Packard

44

ทำงานกับเพรดิเคตเป็นเวลานาน นี่คือข้อสรุปของฉัน (SWIFT)

//Customizable! (for me was just important if at least one)
request.fetchLimit = 1


//IF IS EQUAL

//1 OBJECT
request.predicate = NSPredicate(format: "name = %@", txtFieldName.text)

//ARRAY
request.predicate = NSPredicate(format: "name = %@ AND nickName = %@", argumentArray: [name, nickname])


// IF CONTAINS

//1 OBJECT
request.predicate = NSPredicate(format: "name contains[c] %@", txtFieldName.text)

//ARRAY
request.predicate = NSPredicate(format: "name contains[c] %@ AND nickName contains[c] %@", argumentArray: [name, nickname])

1
เท่ากับLIKE 'a%z'อะไร?
TomSawyer

@ JiříZahálkaคำขอได้ยินหมายถึงอะไร?
Muju

28

ตัวอย่างการใช้งานใน swift 2.0

let dataSource = [
    "Domain CheckService",
    "IMEI check",
    "Compliant about service provider",
    "Compliant about TRA",
    "Enquires",
    "Suggestion",
    "SMS Spam",
    "Poor Coverage",
    "Help Salim"
]
let searchString = "Enq"
let predicate = NSPredicate(format: "SELF contains %@", searchString)
let searchDataSource = dataSource.filter { predicate.evaluateWithObject($0) }

คุณจะได้รับ (สนามเด็กเล่น)

ป้อนคำอธิบายภาพที่นี่


จะเกิดอะไรขึ้นถ้า ... ถ้าฉันมีพจนานุกรมหลายชุด? ฉันจะแยกวิเคราะห์เพื่อรับข้อมูลได้อย่างไร
Revathy Durairajan

1
@RevathyDurairajan คุณต้องการ SELF.yourkeyname สำหรับการกรองอาร์เรย์ของพจนานุกรม
Pawan Rai

11

คุณสามารถใช้ตัวกรองที่มีอยู่อย่างรวดเร็วเพื่อกรองเนื้อหาจากอาร์เรย์แทนที่จะใช้เพรดิเคตเหมือนใน Objective-C

ตัวอย่างใน Swift 4.0 มีดังนี้:

var stringArray = ["foundation","coredata","coregraphics"]
stringArray = stringArray.filter { $0.contains("core") }

ในตัวอย่างข้างต้นเนื่องจากแต่ละองค์ประกอบในอาร์เรย์เป็นสตริงคุณจึงใช้containsวิธีการกรองอาร์เรย์ได้

หากอาร์เรย์มีออบเจ็กต์แบบกำหนดเองคุณสมบัติของออบเจ็กต์นั้นสามารถใช้เพื่อกรององค์ประกอบในลักษณะเดียวกันได้


5

ใช้รหัสด้านล่าง:

 func filterContentForSearchText(searchText:NSString, scopes scope:NSString)
{
    //var searchText = ""

    var resultPredicate : NSPredicate = NSPredicate(format: "name contains[c]\(searchText)", nil)

    //var recipes : NSArray = NSArray()

    var searchResults = recipes.filteredArrayUsingPredicate(resultPredicate)
}

1
ด้วยเหตุผลบางอย่างการเขียนแบบนั้นไม่ได้ผลสำหรับฉัน แต่ให้ myPredicateString = "name มี [c] (searchText)" จากนั้นทำ var resultPredicate: NSPredicate = NSPredicate (format: myPredicateString)
AppHandwerker

5

ฉันคิดว่านี่น่าจะเป็นวิธีที่ดีกว่าใน Swift:

func filterContentForSearchText(searchText:NSString, scope:NSString)
{
   searchResults = recipes.filter { name.rangeOfString(searchText) != nil  }
}

1
นี้เป็นสำนวนมากขึ้นถ้าคุณกรองSequenceแต่มีกรณีที่คุณจะต้องมีเช่นเมื่อต้องรับมือกับNSPredicate NSFetchedResultsController
Jarsen

1

ในเร็ว 2.2

func filterContentForSearchText(searchText: String, scope: String) {
    var resultPredicate = NSPredicate(format: "name contains[c]         %@", searchText)
    searchResults = (recipes as NSArray).filteredArrayUsingPredicate(resultPredicate)
}

ใน Swift 3.0

func filterContent(forSearchText searchText: String, scope: String) {
        var resultPredicate = NSPredicate(format: "name contains[c]         %@", searchText)
        searchResults = recipes.filtered(using: resultPredicate)
    }

1

// เปลี่ยน "name" และ "value" ตามข้อมูลอาร์เรย์ของคุณ

// เปลี่ยนชื่อ "yourDataArrayName" ที่สอดคล้องกับอาร์เรย์ของคุณ (NSArray)

    let resultPredicate = NSPredicate(format: "SELF.name contains[c] %@", "value")

    if let sortedDta = yourDataArrayName.filtered(using: resultPredicate) as? NSArray {

 //enter code here.

        print(sortedDta)
    }
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.