Different Cells in same UITableView - ios

I have got a json result, that looks like this:
[{
"EventDate": "2015-02-19",
"PubEvents": [{
"Title": "Ladies Night",
"Description": "Every thursday is Ladies Night at the Irish House.\nLadies: 2 cocktails for the price of 1 - 1 pint of Crowmoor Cider - 30 kr",
"EventType": "LadiesNight",
"Start": "2015-02-19",
"End": "2015-02-20",
"StartTime": "19:00",
"EndTime": "02:00",
"Image": "ladies.jpg"
}, {
"Title": "Pat Kelly",
"Description": "Pat Kelly from Ireland has extensive experience in entertaining all nationalities, as he has travelled around the world from New York to Amsterdam. He has a very wide repertoire maintaining a traditional approach, and is well received and appreciated for his ability to get his audience excited every night he hits the stage. A “sure thing” evening you will get with the talented Pat.",
"EventType": "Music",
"Start": "2015-02-19",
"End": "2015-02-20",
"StartTime": "21:30",
"EndTime": "01:00",
"Image": "http://domain.dk/Images/Musicians/kelly"
}],
"Matches": [{
"EventType": "Sports",
"Start": "2015-02-19",
"End": "2015-02-19",
"StartTime": "18:00",
"EndTime": "19:00",
"HomeTeam": {
"Id": 0,
"TeamName": "Hold",
"HomeImageUrl": "defaultHome.png",
"AwayImageUrl": "defaultAway.png",
"Badge": "defaultBadge.png"
},
"AwayTeam": {
"Id": 0,
"TeamName": "AndetHold",
"HomeImageUrl": "defaultHome.png",
"AwayImageUrl": "defaultAway.png",
"Badge": "couldn't get an away team"
}
}]
}, {
"EventDate": "2015-02-20",
"PubEvents": [{
"Title": "Pat Kelly",
"Description": "Pat Kelly from Ireland has extensive experience in entertaining all nationalities, as he has travelled around the world from New York to Amsterdam. He has a very wide repertoire maintaining a traditional approach, and is well received and appreciated for his ability to get his audience excited every night he hits the stage. A “sure thing” evening you will get with the talented Pat.",
"EventType": "Music",
"Start": "2015-02-20",
"End": "2015-02-21",
"StartTime": "22:30",
"EndTime": "02:00",
"Image": "http://domain.dk/Images/Musicians/kelly"
}],
"Matches": []
},
An Array of Events in the format:
var eventDate : String?
var pubEvents : Array<PubEvent>?
var matches : Array<Match>?
numberOfSectionsInTableView is eventarray.count, as every date is distinct
numberOfRowsInSection:
let event = self.eventarray[section]
let matchesCount = event.matches?.count ?? 0
let pubEventsCount = event.pubEvents?.count ?? 0
return matchesCount + pubEventsCount
Since every section has x number of matches and x number of pubEvents i need a combined count of the amount of each.
Here is my problem:
I would need to insert the pubevents (if any) and the matches (if any) in the tableview, but I can't figure it out with Swift.
Edit
Philip Mills helped: A very quick implementation:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
let event = self.eventarray[indexPath.section] as SortedEvent
let matchesCount = event.matches?.count ?? 0
let pubEventsCount = event.pubEvents?.count ?? 0
if indexPath.row < matchesCount{
cell.textLabel?.text = "\(event.matches![indexPath.row].homeTeam!.teamName!) v \(event.matches![indexPath.row].awayTeam!.teamName!)"
cell.detailTextLabel?.text = "\(event.matches![indexPath.row].startTime!) - \(event.matches![indexPath.row].endTime!)"
}
else{
cell.textLabel?.text = event.pubEvents![indexPath.row - matchesCount].title!
cell.detailTextLabel?.text = "\(event.pubEvents![indexPath.row - matchesCount].startTime!) - \(event.pubEvents![indexPath.row - matchesCount].endTime!)"
}
return cell
}

When you're given an index path to provide a cell, see if the row is less than the count of matches. If it is, use that match. If it's not less, subtract the count of matches from the row and use that as the index of the pub event you want.

Related

Filter Array of objects on the basis of string value in ios

I want to filter my array on the basis of string value but am not able to do so. Please help me to do this. Below is my array data.
Data Array:
[["LocationCode": UP, "GSTN":, "CompanyCode": JVL, "SRNO": , "Description": Employees of Jubilant Ingrevia (other than SEZ units, Bharuch) who stay in hotel which is located in Uttar Pradhesh, "Company": Jubilant Ingrevia Limited, "Location": Uttar Pradesh, "Address": Bhartiagram, NH-24, Gajraula, Amroha - 244223], ["GSTN":, "CompanyCode": JVL, "Company": Jubilant Ingrevia Limited, "LocationCode": GJ, "Address": 133, Savli Jarod Road, Samlaya, Vadodara - 391520, "Description": Employees of Jubilant Ingrevia (other than SEZ units, Bharuch) who stay in hotel which is located in Gujarat, "Location": Gujarat, "SRNO": ], ["Address": Nira (R.S.), Village Nimbut, Tal. Baramati, Pune - 412102, "Company": Jubilant Ingrevia Limited, "Location": Maharashtra, "GSTN":, "Description": Employees of Jubilant Ingrevia (other than SEZ units, Bharuch) who stay in hotel which is located in Maharashtra, "SRNO": , "LocationCode": MH, "CompanyCode": JVL], ["Location": Telangana, "Address": 304 305, 3rd Floor, Doshi Chambers, Opp. United Insurance Building, Basheerbagh, Ranga Reddy, Hyderabad, Telangana - 500029, "Company": Jubilant Ingrevia Limited, "CompanyCode": JVL, "Description": Employees of Jubilant Ingrevia (other than SEZ units, Bharuch) who stay in hotel which is located in Telangana, "SRNO": , "LocationCode": TL, "GSTN":], ["Address": Plot 1A, Sector 16A, Institutional Area, Noida,Gautam Buddha Nagar, Uttar Pradesh, 201301, "Company": Jubilant Pharmova Limited, "Description": Employees of Jubilant Pharmova who stay in hotel which is located in Uttar Pradesh, "LocationCode": UP, "Location": Uttar Pradesh, "CompanyCode": JOL, "GSTN":, "SRNO": ]]
My Code for filter:
var mergedArray:[Dictionary<String,Any>] = []
for item in dataArray {
if !mergedArray.contains(where: {($0["Company"] as! String) == items}) {
//uniqueArray.append(item)
var dict = item as! [String: Any]
mergedArray.append(dict)
dataArray = mergedArray
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
may be like this :
for item in dataArray {
if !mergedArray.contains(where: {($0["Company"] as! String) == items}) {
//uniqueArray.append(item)
let dict = item as [String: Any]
mergedArray.append(dict)
}
}
dataArray = mergedArray // moved dataArray outside loop

Configuring collectionView:cellForRowAt based on an array of strings

I've got this JSON data (not verbatim) that I get from the backend. It contains the actual data and an array of strings describing the sequence of cells to be shown:
{
"data": [
{
"name": "text",
"data": {
"text": "some text"
}
},
{
"name": "pic",
"data": {
"url": "https://somepic.jpg",
"text": "picture"
}
},
{
"name": "switcher",
"data": {
"id": 1,
"options": [
{
"id": 0,
"text": "option 1"
},
{
"id": 1,
"text": "option 2"
},
{
"id": 2,
"text": "option 3"
}
]
}
}
],
"view": [
"text",
"pic",
"switcher",
"text"
]
}
The problem is that I can't get my head around how to configure cellForRowAt: and get the right order of cells in one section. (i.e. text, pic, selector, text).
I tried a couple of things:
Looping through "view" array and switching on each individual view string to dequeue a specific cell but that doesn't seem to work since returning a cell from a switch case gives a "unexpected non-void return value in void function" error.
I was also thinking about turning a "view" array into a dictionary and then, based on keys in it, dequeue a specific cell but then again, a dictionary should have unique keys meaning that I will not have 2 "text" entries, one of them will be lost.
So, the questions is: how can I dequeue specific cells based on the array of strings? It's also important to understand that it should be done in one section. I'm feeling that it's somehow not that difficult to implement but I'm kinda lost right now. Thanks!
you need to transform your view list and data array into an array of cell contents that you can use inside the TableViewDelegate and TableViewSource method :
var cellsContents : [Int] = []
for aView in view {
var found = false
var index = 0
for aData in data {
if !found {
if let name = aData["name"] as? String {
if aView == name {
found = true
cellsContents.append(index)
continue
}
}
index = index + 1
}
}
}
Then :
number of rows : cellsContents.count
type and contents for a row : data[cellsContents[indexPath.row]]["name"] and data[cellsContents[indexPath.row]]["data"]

Sort through JSON to find each instance that a string is different

I am attempting to find each instance of the string name: being different.
As for the example of JSON below I want to pull Alamo Draft House Lamar and Alamo Draft House Ritz and place them into an array.
JSON:
[{
"tmsId": "MV011110340000",
"rootId": "15444050",
"subType": "Feature Film",
"title": "Bohemian Rhapsody",
"releaseYear": 2018,
"releaseDate": "2018-11-02",
"titleLang": "en",
"descriptionLang": "en",
"entityType": "Movie",
"genres": ["Biography", "Historical drama", "Music"],
"longDescription": "Singer Freddie Mercury, guitarist Brian May, drummer Roger Taylor and bass guitarist John Deacon take the music world by storm when they form the rock 'n' roll band Queen in 1970. Surrounded by darker influences, Mercury decides to leave Queen years later to pursue a solo career. Diagnosed with AIDS in the 1980s, the flamboyant frontman reunites with the group for Live Aid -- leading the band in one of the greatest performances in rock history.",
"shortDescription": "Singer Freddie Mercury of Queen battles personal demons after taking the music world by storm.",
"topCast": ["Rami Malek", "Lucy Boynton", "Gwilym Lee"],
"directors": ["Bryan Singer"],
"officialUrl": "https://www.foxmovies.com/movies/bohemian-rhapsody",
"ratings": [{
"body": "Motion Picture Association of America",
"code": "PG-13"
}],
"advisories": ["Adult Language", "Adult Situations"],
"runTime": "PT02H15M",
"preferredImage": {
"width": "240",
"height": "360",
"uri": "assets/p15444050_v_v5_as.jpg",
"category": "VOD Art",
"text": "yes",
"primary": "true"
},
"showtimes": [{
{
"theatre": {
"id": "9489",
"name": "Alamo Drafthouse at the Ritz"
},
"dateTime": "2018-11-10T19:15",
"barg": false,
"ticketURI": "http://www.fandango.com/tms.asp?t=AAUQP&m=185586&d=2018-11-10"
}, {
"theatre": {
"id": "9489",
"name": "Alamo Drafthouse at the Ritz"
},
"dateTime": "2018-11-10T22:30",
"barg": false,
"ticketURI": "http://www.fandango.com/tms.asp?t=AAUQP&m=185586&d=2018-11-10"
}, {
"theatre": {
"id": "5084",
"name": "Alamo Drafthouse South Lamar"
},
"dateTime": "2018-11-10T12:00",
"barg": false,
"ticketURI": "http://www.fandango.com/tms.asp?t=AATHS&m=185586&d=2018-11-10"
}, {
"theatre": {
"id": "5084",
"name": "Alamo Drafthouse South Lamar"
},
"dateTime": "2018-11-10T15:40",
"barg": false,
"ticketURI": "http://www.fandango.com/tms.asp?t=AATHS&m=185586&d=2018-11-10"
},
}]
}]
Here is my api code:
var shows = [Shows]()
struct Shows: Codable {
let showtimes: [Showtimes]
struct Showtimes: Codable {
let theatre: Theater
struct Theater: Codable {
let id: String
let name: String
}
}
}
func loadShowtimes() {
let apiKey = ""
let today = "2018-11-10"
let zip = "78701"
let filmId = "MV011110340000"
let radius = "15"
let url = URL(string: "http://data.tmsapi.com/v1.1/movies/\(filmId)/showings?startDate=\(today)&numDays=5&zip=\(zip)&radius=\(radius)&api_key=\(apiKey)")
let request = URLRequest(
url: url! as URL,
cachePolicy: URLRequest.CachePolicy.reloadIgnoringLocalCacheData,
timeoutInterval: 10 )
let session = URLSession (
configuration: URLSessionConfiguration.default,
delegate: nil,
delegateQueue: OperationQueue.main
)
let task = session.dataTask(with: request, completionHandler: { (data, response, error) in
if let data = data {
do { let shows = try! JSONDecoder().decode([Shows].self, from: data)
self.shows = shows
}
}
})
task.resume()
}
How would I approach sorting through the array and finding each instance of name: being different, then take each name and place them into a new array?
There are several ways to iterate through your array of Shows and their array of Theater to get the complete list of names. Once you have the full list of names you can get a unique list of those names.
Here is one approach:
let names = Array(Set(shows.map { $0.showtimes.map { $0.theatre.name }}.reduce([]) { $0 + $1 }))
Let's split that up to better explain what is going on.
let allNames = shows.map { $0.showtimes.map { $0.theatre.name }}.reduce([]) { $0 + $1 }
let uniqueNames = Array(Set(allNames))
The shows.map iterates through each Shows in shows. The inner map in turn iterates each Theatre in each of those Shows returning its name. So the inner map gives an array of names. The first map results in an array of arrays of names. The reduce merges those arrays of names into a single array of names leaving allNames with a single array containing every name.
The use of Array(Set(allNames)) first creates a unique set of the names and then it creates an array from that set.
If you want the final result to be sorted alphabetically then add .sorted() to the end.
If you need to keep the original order you can make use of NSOrderedSet and remove any use of sorted.
let names = NSOrderedSet(array: shows.map { $0.showtimes.map { $0.theatre.name }}.reduce([]) { $0 + $1 }).array as! [String]

Passing image from collectionview(based on json)

I have 2 json responses in this format...
//1 {
"product_id": "22",
"product_name": "asd",
"product_description": "Test",
"rating_count": 0,
"product_images": [
{
"id": "973",
"image": "http://myappp.com/uploads/products/16_546_4_image",
"is_default": "0"
},
{
"id": "988",
"image": "http://myappp.com/uploads/products/123_45_67_image",
"is_default": "0"
},
{
"id": "989",
"image": "http://myappp.com/uploads/products/123_45_6_image",
"is_default": "1"
}
]
},
//2 {
"product_id": "5",
"product_name": "cake",
"product_description": "The boss and Anchor Hocking are you doing today hope",
"rating_count": 0,
"product_images": [
{
"id": "962",
"image": "http://myappp.com/uploads/products/123_546_image",
"is_default": "1"
}
]
}
These are associated with 2 collectionview cells. Here I have an array called product_images with some parameters. Now I have a collectionview on which I'm displaying only those images from the url which have an is_default value of 1. I'm doing it like so...
for anItem in productData {
var productImages :[ProductImage] = [] //ProductImage is a struct having parameters myid, url and isDefault
if let images = anItem["product_images"] as? [[String:String]] {
if let defaultImage = images.first(where: {$0["is_default"] == "1"}) {
let productImage = ProductImage(myId: defaultImage["id"]!,
url: URL(string: defaultImage["image"]!)!,
isDefault: true)
productImages.append(productImage)
} } }
So if a collection view item shows an image then that image has an is_default value of 1. But each cell will also have associated with it the other images also with is_default value of 0 and other parameters like product_id, product_name etc. But only thing is what is shown in the collection view is the image with an is_default value of 1.
Now what I want to achieve is when I click on a collectionview cell I want to pass to another view not just the image shown on the cell but also the other images associated with a cell with an is_default value of 0. So if have 2 collectionview cells and each of them has the values of 1st and 2nd json(given above) respectively, then on the click of the first collectionviewcell I should be able to show 3 images and on the click of the 2nd collectionviewcell I should be able to show just 1 image.
Hope somebody can help...

Merging a complex data structure of NSArray and NSDictionary

I have the following data structure Snapshot which is a combination of nested arrays and dictionaries:
{"Snapshot": {
"ask": [
{
"price": 101.42,
"size": 7
},
{
"price": 101.85,
"size": 5
}
],
"bid": [
{
"price": 89.72,
"size": 79
},
{
"price": 89.71,
"size": 158
}
]
}}
The existing structure from above should be updated by the price and size entries in the following dictionary / array structure:
{"Refresh": {
"ask": [],
"bid": [
{
"price": 89.71,
"size": 666
}
],
}}
In this example, the value size for the bid item which has the price: 89.71 should be updated from 158 to 666. If the price does not exist yet, a new item with the price and size from the Refresh data structure should be added. If size = 0, the price and size item should be removed.
I have tried to do this with the methods addEntriesFromDictionary and addObjectsFromArray but did find a solution to my problem.
What would be the fastest way to do this?
How would you recommend to merge these two data structures?
Thank you!
Assuming the dictionaries are named snapshot and refresh...
snapshot[#"Snapshot][#"bid"] = [snapshot[#"Snapshot][#"bid"] arrayByAddingObjectsFromArray:refresh[#"Refresh"][#"bid]];
More complicated union of the arrays will just require more code. And if you want price to be a unique key, why not make it a key?

Resources