JSON response like this
{
"result": {
"cities": [
{
"id": 1,
"city": "North and Middle Andaman",
"state_id": 32
},
{
"id": 2,
"city": "South Andaman",
"state_id": 32
},
{
"id": 3,
"city": "Nicobar",
"state_id": 32
},
{
"id": 330,
"city": "Mumbai suburban",
"state_id": 12
},
I am showing cities in textfield with TextFieldEditingChanged and dropdown
code: with this code i can show city list in dropdown and got selected city in textfield but i need selected city id as well.. which i am unable to get
if i print print(item, self?.cityId). here Mumbai suburban id is 330 but got dropdown index 2... how do i get selected city id from dropdown, please guide me
o/p
Mumbai suburban Optional(2)
#IBAction func cityTextFieldEditingChanged(_ sender: UITextField) {
var tempArray = [String]()
if sender.text?.count != 0 {
for eachData in cityResultDict?.cities ?? []{
if let wordToSearch = sender.text{
let range = eachData.city?.lowercased().range(of: wordToSearch, options: .caseInsensitive, range: nil, locale: nil)
if range != nil {
tempArray.append(eachData.city ?? "")
}
}
}
}
showDropDown(with: tempArray, from: sender) { [weak self] (item, index) in
self?.locationTextField.text = item
self?.cityId = cityResultDict?.cities?[index].id ?? 0
print(item, self?.cityId)
}
}
if i print print(item, self?.cityId). here Mumbai suburban id is 330 but got dropdown index 2..
Because you are making a new array which is tempArray matching with your search condition when you showDropDown.
I don't know how you implement your showDropDown. But this is a key for your code
Code will be like this
var tempArray = [String]()
var tempCityId = [String]() // I not recommend slipt like this which one is for name city and one is for your id
if sender.text?.count != 0 {
for eachData in cityResultDict?.cities ?? []{
if let wordToSearch = sender.text{
let range = eachData.city?.lowercased().range(of: wordToSearch, options: .caseInsensitive, range: nil, locale: nil)
if range != nil {
tempArray.append(eachData.city ?? "")
// make new array to store your cityId too
tempId.append(eachData.cityId ?? "")
}
}
}
}
showDropDown(with: tempArray, from: sender) { [weak self] (item, index) in
self?.locationTextField.text = item
self?.cityId = tempCityId[index].id ?? 0 // get the id form your tempCityId too
print(item, self?.cityId)
}
Notice: This way I don't recommend. You can make a new struct which store all your reaching City or a struct only store your cityName and cityId which easier for you.
I build this way just for easier for you to realize and because I don't know how you build your showDropDown
Related
I am getting string of ints, i need to convert that in array if ints
i need like this [8,9,10]
let stringOfints = "8,9,10"
let arrOfIds = stringOfints?.components(separatedBy: ",")
0/p:
["8","9", "10"]
EDIT: here i need to check id with string of ints
my json like this
{
"jsonrpc": "2.0",
"result": {
"sub_category": [
{
"id": 2,
"title": "Logo Design"
},
{
"id": 3,
"title": "banner design"
},
{
"id": 5,
"title": "business web site"
},
{
"id": 10,
"title": "Business Card Design"
}
]
}
}
code: here arrOfIds are [2, 3] but when i compare arrOfIds with json id and if its match then appending its title to arrSubCat but if i print arrSubCat at end of for loop then why all titels are coming...plz help
var arrSubCat:[String] = []
private func getSubCategoryServiceIDs() {
let param = ["category_id" : categoryID!]
APIReqeustManager.sharedInstance.serviceCall(param: param, url: CommonUrl.get_sub_category) { [weak self] (resp) in
self?.getSubCategoryIDs = GetSubCatModel(dictionary: resp.dict as NSDictionary? ?? NSDictionary())
if self?.getServiceDetails?.result?.serviceDetails?.sub_cat_group != nil{
let kat = self?.getSubCategoryIDs?.result?.sub_category ?? []
let value = self?.getServiceDetails?.result?.serviceDetails?.sub_cat_group
let arrOfIds = value?.components(separatedBy: ",").compactMap { Int($0) }
for singleCat in kat{
if ((arrOfIds?.contains(singleCat.id ?? 0)) != nil){
self?.arrSubCat.append(singleCat.title ?? "")
}
}
print("array of sub cat \(self?.arrSubCat)")//getting all titles why?
self?.collectionView.reloadData()
}
}
}
o/p
array of sub cat (["Logo Design", "banner design", "business web site", "Business Card Design"])
Previous Answer
You have to convert the String to Int
let stringOfints = "8,9,10"
let arrOfIds = stringOfints.components(separatedBy: ",").compactMap { Int($0) }
Updated Answer
Modify the code inside API call like below and try.
let arrOfIds = value?.components(separatedBy: ",").compactMap { Int($0) } ?? []
for singleCat in kat {
if arrOfIds.contains(singleCat.id ?? 0) {
self?.arrSubCat.append(singleCat.title ?? "")
}
}
I have a data as given below:
[["-MXpvzmZdbqzrjND8w9F": {
lid = "-MW6eEidZFCLeeZ0uBk1";
message = hi;
timeStamp = 1617960107264;
title = "Sambhar Dosa";
user = 1QSU0c1q8QNrZzmICXGClC0o86E3;
}, "-MXq5NAyrkk4ZcvRFM7T": {
lid = "-MW6eEidZFCLeeZ0uBk1";
message = "how ru?";
timeStamp = 1617962828647;
title = "Sambhar Dosa";
user = 1QSU0c1q8QNrZzmICXGClC0o86E3;
}], ["-MXqa5-pkC28lY_Q_hpZ": {
lid = "-MWwEpHAhIdhN0i5sltB";
message = "hi nice cycle";
timeStamp = 1617971142820;
title = "Cycle for kids";
user = 1QSU0c1q8QNrZzmICXGClC0o86E3;
}]]
Now this value is defined by the variable testarray. Name given just for convenience.
The testarray is var testArray = [String: [String: Any]]
Inner dictionary is defined using a struct as given below:
struct SomeData1
{
let dict: [String: Any]
var lid: String? { dict["lid"] as? String }
var message: String? { dict["message"] as? String }
var timeStamp: Double { dict["timeStamp"] as? Double ?? 0.0 }
var title: String? { dict["title"] as? String }
var user: String? { dict["user"] as? String }
var owner: String? { dict["owner"] as? String }
}
So testarray can also be read as var testArray = [String: [SomeData1]]
Now as per the above data,when the lid matches with a particular value,then only those data is stored in a variable called dataToDisplay which is defined as var dataToDisplay = SomeData1
I have filtered the above data using the below code
var sortStep1 = self.testArray.map {
dict in dict.map {
($0.key, SomeData1(dict: $0.value))
}.filter {$0.1.lid == self.listid}
}
print("sortStep1 is",sortStep1)
the value displayed for sortStep1 is
[[("-MY5aPJ--Xoot_wlGSqS", Hungry.ChatVC.SomeData1(dict: ["owner": bPqDIJvYX7g7ZhE8ap0TgeYMYjE2, "lid": -MW6eEidZFCLeeZ0uBk1, "user": 1QSU0c1q8QNrZzmICXGClC0o86E3, "timeStamp": 1618239661393, "message": hi, "title": Sambhar Dosa])), ("-MY5b-WT4AoWWa7c1eQT", Hungry.ChatVC.SomeData1(dict: ["title": Sambhar Dosa, "message": nice product, "user": 1QSU0c1q8QNrZzmICXGClC0o86E3, "timeStamp": 1618239817904, "lid": -MW6eEidZFCLeeZ0uBk1, "owner": bPqDIJvYX7g7ZhE8ap0TgeYMYjE2]))], []]
Here there is a null array which is also shown.i do not want this null array.i want only matching list to be displayed.
Is the code for fetching matched lid correct?
In tableview, each cell with key and value labels, i can able to pass static key value to tableview but now trying to get data from Json response to show in tableview.
here is my json response:
{
"d": {
"results": [
{
"__metadata": {
"id": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"uri": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"type": "Z_MM_PO_01_SRV.POItemSet"
},
"PoDocNo": "4500022401",
"Item": "00010",
"Material": "RMECC_MOB1",
"StorageLocation": "3001",
"MatGroup": "00107",
"Quantity": "2.000",
"OrderUnit": "KG",
"NetPrice": "1000.000",
"UnitofPrice": "1.000",
"ItemCat": "0",
"Requistor": ""
},
{
"__metadata": {
"id": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"uri": "http://192.168.41.27:8009/sap/opu/odata/sap/Z_MM_PO_01_SRV/POItemSetSet('4500022401')",
"type": "Z_MM_PO_01_SRV.POItemSet"
},
"PoDocNo": "4500022401",
"Item": "00020",
"Material": "RMECC_MOB1",
"StorageLocation": "3001",
"MatGroup": "00107",
"Quantity": "2.000",
"OrderUnit": "KG",
"NetPrice": "1000.000",
"UnitofPrice": "1.000",
"ItemCat": "0",
"Requistor": ""
}
]
}
}
here i'm getting json response:
extension PoItemDetailsViewController {
func GetPoItemCount() {
if orderNo != nil {
// Call API
print("orderni::\(orderNo!)")
PoVendorListApiManager.sharedInstance.getPoListWithModel(orderString: orderNo!){ (json:JSON) in
// return json from API
if let categories = json["d"]["results"].dictionary {
print("catefory::\(self.categories)")
for (key, value) : (String, JSON) in categories {
self.dict[key] = value.object as AnyObject
}
print("dict:::\(self.dict)")
// for key in categories.keys {
// if let category =
categories[key]?.stringValue {
//
self.categories.updateValue(category, forKey: key)
// }
//
// }
}
print("catefory::\(self.categories)")
}
}
}
}//extension
here is my model:
import SwiftyJSON
struct poItems {
var key: String?
var value: String?
}
here is my static value i have passed to table view:
private var PoItems: [poItems]?
private var poVendorItemArray = [PoVendorModel]()
private func loadPoItems() -> [poItems] {
var tempItems = [poItems]()
let item1 = poItems.init(key: "Material#", value: "")
let item2 = poItems.init(key: "Quantity", value: "Bottles")
let item3 = poItems.init(key: "StorageLocation", value: "KP04")
let item4 = poItems.init(key: "PoDocNo", value: "KP Suppliers")
let item5 = poItems.init(key: "NetPrice", value: "1000")
return tempItems
}
how can i pass json reponse with key and value dynamically into tableview?
Any help much appreciates pls...
Please reread my answer in your earlier question (or read the JSON)
The value for results is an array
if let categories = json["d"]["results"].array {
print("category::\(self.categories)")
for category in categories {
for (key, value) in category {
print(key, value)
}
}
}
And – as suggested in many of your previous questions and in the comments – you are encouraged to drop SwiftyJSON and use Codable.
Let's say I have an array of 3 dictionaries in JSON and each of those has it's own type (demo, entry, comment).
[
{
"_id": "random ID",
"profile": "random ID Profile",
"demo": {
"_id": "random ID",
"profile": {
"_id": "random ID",
"name": "name",
"username": "username",
"description": "description",
"picture": "/picture"
},
"path": "/path",
"created": "date"
},
"type": "demo",
"source": "570aa8f647a70780a7111e91",
"__v": 0,
"created": "date"
},
{
"_id": "random ID",
"comment": "random comment ID",
"type": "comment",
"source": "57077c4e356c10371ca91ad9",
"__v": 0,
"created": "date"
},
{
"_id": "random ID",
"entry": "random entry ID",
"type": "entry",
"source": "57077c4e356c10371ca91ad9",
"__v": 0,
"created": "date"
}
]
Right now I'm checking the type in the request so I only get the demo.
func getTimeline(urlString: NSURL, completion: ([ModelDemos]) -> Void) {
Alamofire.request(.GET, urlString).responseJSON { response in
if let httpResponse = response.response {
switch httpResponse.statusCode {
case 200:
var modelTimeline = [ModelDemos]()
if let demos = response.result.value as? [JSONDictionary] {
for demo in demos {
if let type = demo["type"] as? String {
if type == "demo" {
if let demo = demo["demo"] as? JSONDictionary {
let JSON = ModelDemos(data: demo)
modelTimeline.append(JSON)
}
}
}
}
} else { print("not working") }
dispatch_async(dispatch_get_main_queue()) {
completion(modelTimeline)
print("Am I back on the main thread ? Response: \(NSThread.isMainThread())")
}
default:
return
}
}
}
}
After this setting a completion method in my TimelineViewController
var timelineDemos = [ModelDemos]()
func runApiManagerTimeline() {
guard let urlString = urlString else {return}
apiManagerCurrentUserProfile.getTimeline(urlString, completion: didGetCurrentUserProfileDemos)
}
func didGetCurrentUserProfileDemos(demos: [ModelDemos]) {
timelineDemos = demos
timelineCollectionView.reloadData()
}
All works fine, I get only the demo Dictionary and I can load it to the DemoUITableViewCell.
Now I have to create 3 different types of UITableViewCell for each of the Dictionary from the array. Imagine it as a Facebook feed where each Dictionary is different and the number is continuously growing.
How would I tell each Cell what content it should load?
Just another good example to use a custom struct as model for the data source array.
First create an enum to map the String types to enum cases
enum DataType : String { case Demo = "demo", Comment = "comment", Entry = "entry" }
Create a custom struct item as data source model. Declare all common properties of the three data types without an initial value, individual properties with a initial value to use the implicit memberwise initializer to create the Item instance and assign values to the individual properties depending on the type. The sample properties are from the JSON and only an example
struct Item {
// common properties
var type : DataType
var source : String
var created : String
// individual properties
var username = ""
var description = ""
var picture = ""
}
In the TableView controller create the data source array
var modelTimeline = [Item]()
and create Item instances while parsing the JSON
...
if let demos = response.result.value as? [JSONDictionary] {
for demo in demos {
if let type = demo["type"] as? String {
let source = type["source"] ?? ""
let created = type["date"] ?? ""
var item = Item(type: DataType(rawValue:type), source: source, created: created)
if type == "demo" {
if let demo = demo["demo"] as? JSONDictionary, profile = demo["profile"] as? JSONDictionary {
item.username = profile["username"] ?? ""
item.description = profile["description"] ?? ""
item.picture = profile["picture"] ?? ""
}
}
modelTimeline.append(item)
}
}
} else { print("not working") }
...
In cellForRowAtIndexPath create cells and assign values to the UI elements depending on the type
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let item = modelTimeline[indexPath.row]
switch item.type {
case .Demo:
let cell = tableView.dequeueReusableCellWithIdentifier("DemoCell", forIndexPath: indexPath) as! DemoUItableViewCell
cell.usernameLabel.text = item.username
cell.descriptionLabel.text = item.description
cell.sourceLabel.text = item.source
// populate other UI elements
return cell
case .Comment:
cell = tableView.dequeueReusableCellWithIdentifier("CommentCell", forIndexPath: indexPath) as! CommentUItableViewCell
cell.sourceLabel.text = item.source
// populate other UI elements
return cell
case .Entry:
cell = tableView.dequeueReusableCellWithIdentifier("EntryCell", forIndexPath: indexPath) as! EntryUItableViewCell
cell.sourceLabel.text = item.source
// populate other UI elements
return cell
}
}
The code is not a full working version, it's just a suggestion how to use different cells for different types.
With those methods:
// MARK: - Table view Functions
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
//3 because of 3 different dictionaries
return 3
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
//Define the amount of rows for each section
if (section == 0) {
return --amount of entries in regarding dictionary--
} else if (section == 1) {
return --amount of entries in regarding dictionary--
} else {
return --amount of entries in regarding dictionary--
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if (indexPath.section == 0) {
//Dict 1
} else if (indexPath.section == 1) {
//Dict 2
} else {
//Dict 3
}
I think you can try to customize your datasource making a class (internal class or not) like:
class GeneralNotificationInfo: NSObject {
var notificationTime:NSDate! = NSDate()
enum notificationType: Int {
case Demo = 1
case Entry = 2
case Test = 3
}
var data:NSDictionary! = NSDictionary()
...
}
With this personalization you can easily handle your cell.
About your code:
typealias AlamoNetSuccess = (result: NSDictionary?) -> Void
typealias AlamoNetProgress = (result: NSDictionary?) -> Void
typealias AlamoNetFailure = (error: NSDictionary?) -> Void
var params :[String: AnyObject]? = ["user": "David", "age": 40]
func getTimeline(urlString: NSURL,params: [String: AnyObject], success successBlock :AlamoNetSuccess,
failure failureBlock :AlamoNetFailure) {
.request(.GET, url, parameters: params, encoding: ParameterEncoding.URL)
.responseJSON { response in
print("∙ ---")
print("∙ Net URLs: \(response.request?.URL)") // original URL request
print("∙ ---")
//print(response.response) // URL response
//print(response.data) // server data
//print(response.result) // result of response serialization
if response.result.isSuccess {
let jsonDic = response.result.value as! NSDictionary
successBlock(result: jsonDic)
} else {
let httpError: NSError = response.result.error!
let statusCode = httpError.code
let error:NSDictionary = ["error" : httpError,"statusCode" : statusCode]
failureBlock(error: error)
}
}
let wrappedNetSuccess: AlamoNetSuccess = {(result: NSDictionary?) -> Void in //
print ("∙ Net Success: \(result)")
// do whatever you want with your dictionary, parse it into datasource...
}
let wrappedAPIFailure: AlamoNetFailure = {(error: NSDictionary?) -> Void in
print ("∙ Net Failure: \(error)")
// handle your network error with alertViews or other..
}
apiManagerCurrentUserProfile.getTimeline(urlString,params:[], success: wrappedAPISuccess, failure: wrappedAPIFailure)
I have an array of AnyObject objects in Swift (eventually, this array will be populated by querying a Parse database). Each object in the array has attributes of a publication, such as fullTitle, url, and journal. How can I filter the array to select all objects that match the search string for any value (e.g. where the fullTitle, url, or journal include "Forbes")?
Below is example code from a playground. First the sample array:
var publication1 = [
"fullTitle": "My first blog",
"url": "www.forbes.com/post1",
"journal": "Forbes
]
var publication2 = [
"fullTitle": "My second blog",
"url": "www.wsj.com/post1",
"journal": "Wall Street Journal"
]
var publications: [AnyObject] = [publication1, publication2]
Then, the filter function:
func filterContentForSearchText(searchText: String) {
let filteredPublications = publications.filter() {
if let fullTitle = ($0)["fullTitle"] as? String {
return fullTitle.rangeOfString(searchText) != nil
} else {
return false
}
}
}
Now, if I call the function with "first" as an argument, it should return the first object out of the array:
println(filterContentForSearchText("first"))
However, this command gives no result. How can I fix this? Also, how can I query all fields of the object for the searchText, not just the fullTitle field?
Thank you.
Here's a simple example that returns an array of matches in all fields:
func filterContentForSearchTextInAllFields(searchText: String) -> [String] {
var results = [String]()
for publication in publications {
for (key, value) in publication {
if (value as NSString).containsString(searchText) {
results.append(value)
}
}
}
return results
}
println(filterContentForSearchTextInAllFields("blog"))
This one only works on titles:
func filterContentForSearchText(searchText: String) -> [String] {
var results = [String]()
for publication in publications {
if let fullTitle = publication["fullTitle"] {
if (fullTitle as NSString).containsString(searchText) {
results.append(fullTitle)
}
}
}
return results
}
println(filterContentForSearchText("first"))
UPDATE
Here's a version for what you've asked in the comments:
func filterContentForSearchText(searchText: String) -> [[String:String]] {
var results = [[String:String]]()
for publication in publications {
if let fullTitle = publication["fullTitle"] as? String {
if (fullTitle as NSString).containsString(searchText) {
results.append(publication as! [String : String])
}
}
}
return results
}
println(filterContentForSearchText("first"))
Your "rows" are dictionaries: in the loop we assign each one to the "publication" variable, so we just take the one whose title matches the search terms then append it to an array of dictionaries.
Here is the route I went. Instead of an array of AnyObject I just let Swift infer the type
var publications = [publication1, publication2]
func searchPublications(seachText: String) -> [[String: String]] {
let filteredPublications = publications.filter { $0
for (_, value) in $0 {
if let found = value.rangeOfString(seachText, options: NSStringCompareOptions.CaseInsensitiveSearch, range: Range<String.Index>(start: value.startIndex, end: value.endIndex), locale: NSLocale.currentLocale()) {
return true
}
}
return false
}
return filteredPublications
}
Swift 3.0
This is worked for me.
I want filter data by it's status 0 or 1.
var arrRooms:[[String:AnyObject]] = [
[
"id": 30 as AnyObject,
"name": "Earth" as AnyObject,
"status": 0 as AnyObject,
"duration": 10 as AnyObject
],
[
"id": 27 as AnyObject,
"name": "Mars" as AnyObject,
"status": 1 as AnyObject,
"duration": 0 as AnyObject
]
]
let StatusPredicate = NSPredicate(format: "status = 1 ")
let arrFilter:[[String:AnyObject]] = (arrRooms as NSArray).filtered(using: StatusPredicate) as! [[String : AnyObject]]
print(arrFilter);
// output [["name": Mars, "status": 1, "id": 27, "duration": 0]]
it may be useful.thanks