Collectionview Not Display Data After Parsing JSON

CollectionView not display data after parsing JSON

As this

GettingMoney.fetchData()

is a sign of asynchronous process that doesn't reload the collection , so do

func fetchData(completion:@escaping ([String]) -> ()) {
Api.load {
completion(arr)
}
}

Then use like

GettingMoney.fetchData { arr in
self.arraOfData = arr
DispatchQueue.main.async {
self.collectionView.reloadData()
}
}

A not direct case like yours is here Returning data from async call in Swift function

Collection View Not Showing Data

Try instead of

nc.post(name: Notification.Name("didFinishParsing"), object: nil)

send

nc.post(name: Notification.Name("didFinishParsing"), object: news)

Then instead of

guard let news = notification.object as? Article else { return}

write

guard let news = notification.object as? News else { return}
print("News == \(news)")
self.news = news.articles

How to parse json Data into dynamic collection view sections and cells in swift

First of all declare the struct with uppercased name, with non-optional members and without the init method.

struct JobsData : Decodable
{
let employeeName : String
let startTime : String
let endTime : String
var startDate : String
}

To group the data declare a Section struct

struct Section
{
let title : String
let jobsData : [JobsData]
}

and declare the data source array

var sections = [Section]()

After decoding the array

let jobsDataArray = try JSONDecoder().decode([JobsData].self, from: data)

group it with Dictionary(grouping:by:), map it to a Section array and sort it

let grouped = Dictionary(grouping: jobsDataArray, by: {$0.startDate})
self.sections = grouped.map{Section(title: $0.key, jobsData: $0.value)}
.sorted{$0.title < $1.title}

You can even sort the JobsData items in the sections simultaneously for example by startTime

self.sections = grouped.map{Section(title: $0.key, jobsData: $0.value.sorted{$0.startTime < $1.startTime})}
.sorted{$0.title < $1.title}

To display the sections implement the datasource methods

override func numberOfSections(in collectionView: UICollectionView) -> Int
return sections.count
}


override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return sections[section].jobsData.count
}

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! AvailableJobsCell
let jobData = sections[indexPath.section].jobsData[indexPath.item]
let sTime = self.timeInAmPm(String: jobData.startTime)
let eTime = self.timeInAmPm(String: jobData.endTime)
cell.jobAddedTime.text = "\(sTime) - \(eTime)"
cell.jobTitle.text = jobData.employeeName
cell.schoolName.text = "\(jobData.organizationName ?? "")\n\(jobData.organizationAddress ?? "")"
cell.jobNo.text = jobData.confirmationNumber!
cell.personOnHiatus.text = jobData.positionDescription!
cell.index = indexPath
cell.delegate = self
return cell
}

Swift: How to Display Parsed JSON Data in CollectionView inside a TableView?

Collection view delegate methods don't know context of their collection view. You should calculate onlineNews index depending on the collectionView instance instead of using indexPath.row, which is internal collection view index path.

Edit: better option (to avoid scrolling and layout issues) is to use single collection view, where cells are grouped in rows. If you don't want to make layout manager, you can achieve such layout by adding small, but very wide separator views between sections

Edit2:

cell.contentType.text = categoryResults[indexPath.row]["ContentType"].stringValue

uses local indexPath of this collection view. You could assign tag to tableViewCell.collectionView with a value of desired categoryResults index. Then you can use this tag as in categoryResults[collectionView.tag]

Collectionview not show JSON Parsing image

You should probably use a custom UICollectionViewCell class that has a UIImageView property, init it with a frame that's the same as your UICOllectionView's frame.

Then in your viewController's cellForRow method, use SDWebImage to asynchronously set your cell's custom photo.

Cell Header File

@interface CustomCell: UICollectionViewCell

@property (nonatomic, strong) UIImageView *photo;

@end

Cell Implementation File

@implementation CustomCell

-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];

if(self)
{
self.photo = [[UIImageView alloc] initWithFrame:frame];
self.photo.contentMode = UIViewContentModeScaleAspectFill;

[self.contentView addSubview:self.photo];
}

return self;
}

@end

View Controller Implementation File

#import "CustomCell.h"
#import <SDWebImage/UIImageView+WebCache.h>

-(void)viewDidLoad
{
...
self.collectionView = [[UICollectionView alloc] init....];
self.collectionView registerClass:[CustomCell class] forCellWithReuseIdentifier:@"cellID"];
}

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellID" forIndexPath:indexPath];

// using SDWebImage to download photo asynchronously.

[cell.photo sd_setImageWithURL:[NSURL urlWithString:[json valueForKey:@"imageURL"]] placeholderImage:[UIImage imageNamed:@"placeholderImage.png"]];


}

Spinner

Modify your custom cell class to include a new UIActivitiyIndicator property:

@interface CustomCell: UICollectionViewCell

@property (nonatomic, strong) UIImageView *photo;
@property (nonatomic, strong) UIActivityIndicatorView *spinner;

@end

@implementation CustomCell

-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];

if(self)
{
self.photo = [[UIImageView alloc] initWithFrame:frame];
self.photo.contentMode = UIViewContentModeScaleAspectFill;

self.spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
// might or might not need to set frame of spinner

[self.contentView addSubview:self.photo];
[self.photo addSubview:self.spinner];
}

return self;
}

@end

Then change the SDWebImage call to the one with the completion block:

-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellID" forIndexPath:indexPath];

// using SDWebImage to download photo asynchronously.

[cell.spinner startAnimating];

[cell.photo sd_setImageWithURL:[NSURL urlWithString:[json valueForKey:@"imageURL"]] placeholderImage:[UIImage imageNamed:@"placeholderImage.png"] options:0 completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {

// tell spinner to stop animating after image finished downloading
[cell.spinner stopAnimating];

}];
}

Reloading UICollection view after data parse

Same problem i faced..your url having many images means reload t

dispatch_async(dispatch_get_main_queue(), {
self.collectionView.reloadData()
})


Related Topics



Leave a reply



Submit