Я пытаюсь загрузить данные Json из запроса URL-адреса, сохранить новые объекты в объектах CoreData и отобразить их в виде uitableview.загрузка и сохранение всех данных работают нормально.Моя проблема сводится к отображению его на UITableView.Когда он загружается, ничего не появляется, пока я не коснусь или прокрутить.это вызвало первую проблему, когда отношения не загружались вовремя и не появлялись пустыми в tableView.поэтому я решил подготовить данные в одном объекте перед отображением ячеек.это работает нормально, но осталась одна проблема - я должен нажать, прежде чем данные появятся.
@protocol LokalModelProtocol <NSObject,NSURLSessionDelegate,NSFetchedResultsControllerDelegate>
@required
-(void)itemsDownloaded;
-(void)mediaDownloaded;
@end
@interface LokalModel : NSObject
-(void)downloadItems;
@property (strong, nonatomic) NSMutableData* thedata;
@property (strong, nonatomic) NSString* urlString;
@property (strong, nonatomic) NSURL* theUrl;
@property (strong,nonatomic) id<LokalModelProtocol>delegate;
@property (strong,nonatomic) Media* media;
@property (strong,nonatomic) Post* post;
@property (strong,nonatomic) NSManagedObjectContext* managedObjectContext;
@property (strong,nonatomic) NSFetchedResultsController* fetchedResultsController;
@property (strong,nonatomic) NSPersistentStoreCoordinator* persistentStoreCoordinator;
-(void)parseJson:(NSData*)data;
-(void)parseJsonMedia:(NSData*)data;
-(void)downloadMedia;
@end
@implementation LokalModel;
@synthesize thedata,urlString,theUrl,delegate,persistentStoreCoordinator,post,managedObjectContext,fetchedResultsController;
-(NSManagedObjectContext *) managedObjectContext
{
return [(AppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
-(void)downloadItems{
NSURLSession *currentSession= [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
static NSString* urlString = @"https://balalatet.com/wp-json/wp/v2/posts";
theUrl=[NSURL URLWithString:urlString];
NSURLSessionDataTask *task = [currentSession dataTaskWithURL:theUrl completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error){
[NSException raise:@"error" format:@"%@",error.localizedDescription];
NSLog(@"connection error1");
}
else{
NSLog(@"connection success");
[self parseJson:data];
}
}];
[task resume];
}
-(void)parseJsonMedia:(NSData *)data{
NSArray *jsonResults = [[NSArray alloc]init];
NSError *jsonerror;
@try {
jsonResults =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonerror];
if (jsonerror)
[NSException raise:@"json error" format:@"%@",jsonerror.localizedDescription];
} @catch (NSException *exception) {
NSLog(@"%@", exception.reason);
} @finally {
NSLog(@"ran");
}
NSMutableDictionary *jsonElenent =[NSMutableDictionary dictionary];
dispatch_async(dispatch_get_main_queue(), ^{
[self.managedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
});
for (NSMutableDictionary *d in jsonResults)
{
jsonElenent=d;
dispatch_async(dispatch_get_main_queue(), ^{
self.media = [NSEntityDescription insertNewObjectForEntityForName:@"Media" inManagedObjectContext:[self managedObjectContext]];
self.media.id= [NSString stringWithFormat: @"%@", jsonElenent[@"id"]];
self.media.source_url= [NSString stringWithFormat: @"%@", jsonElenent[@"source_url"]];
NSError *error = nil;
if ([self.managedObjectContext hasChanges])
{
if (![self.managedObjectContext save:&error])
{
NSLog(@"Save Failed: %@", [error localizedDescription]);
}
else
{
NSLog(@"Save media Succeeded");
}
}
});
}
}
-(void)downloadMedia{
NSURLSession *currentSession= [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
static NSString* urlString = @"https://balalatet.com/wp-json/wp/v2/Media";
NSURL *theUrl2=[NSURL URLWithString:urlString];
NSURLSessionDataTask *task3 = [currentSession dataTaskWithURL:theUrl2 completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (error){
[NSException raise:@"error" format:@"%@",error.localizedDescription];
NSLog(@"connection error1");
}
else{
NSLog(@"connection success");
[self parseJsonMedia:data];
}
}];
[task3 resume];
}
-(void)parseJson:(NSData*)data{
NSArray *jsonResults = [[NSArray alloc]init];
NSError *jsonerror;
@try {
jsonResults =[NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&jsonerror];
if (jsonerror)
[NSException raise:@"json error" format:@"%@",jsonerror.localizedDescription];
} @catch (NSException *exception) {
NSLog(@"%@", exception.reason);
} @finally {
NSLog(@"ran");
}
NSMutableArray *posts = [[NSMutableArray alloc] init];
NSMutableDictionary *jsonElenent =[NSMutableDictionary dictionary];
dispatch_async(dispatch_get_main_queue(), ^{
[self.managedObjectContext setMergePolicy:NSMergeByPropertyObjectTrumpMergePolicy];
[self downloadMedia];
});
for (NSMutableDictionary *d in jsonResults)
{
jsonElenent=d;
dispatch_async(dispatch_get_main_queue(), ^{
self.post = [NSEntityDescription insertNewObjectForEntityForName:@"Post" inManagedObjectContext:[self managedObjectContext]];
self.post.id= [NSString stringWithFormat: @"%@", jsonElenent[@"id"]];
self.post.date= [NSString stringWithFormat: @"%@", jsonElenent[@"date"]];
self.post.date_gmt= [NSString stringWithFormat: @"%@", jsonElenent[@"date_gmt"]];
self.post.guid= [NSString stringWithFormat: @"%@", jsonElenent[@"guid"]];
self. post.slug= [NSString stringWithFormat: @"%@", jsonElenent[@"slug"]];
self.post.status= [NSString stringWithFormat: @"%@", jsonElenent[@"status"]];
self.post.sticky= [NSString stringWithFormat: @"%@", jsonElenent[@"sticky"]];
self.post.ping_status= [NSString stringWithFormat: @"%@", jsonElenent[@"ping_status"]];
self. post.type= [NSString stringWithFormat: @"%@", jsonElenent[@"type"]];
self.post.comment_status=[NSString stringWithFormat: @"%@", jsonElenent[@"comment_status"]];
self.post.tags=[NSString stringWithFormat: @"%@", jsonElenent[@"tags"]];
self.post.title=[NSString stringWithFormat: @"%@", jsonElenent[@"title"]];
self. post.template= [NSString stringWithFormat: @"%@", jsonElenent[@"template"]];
self.post.link=[NSString stringWithFormat: @"%@", jsonElenent[@"link"]];
self.post.meta=[NSString stringWithFormat: @"%@", jsonElenent[@"meta"]];
self.post.modified=[NSString stringWithFormat: @"%@", jsonElenent[@"modified"]];
self.post.modified_gmt=[NSString stringWithFormat: @"%@", jsonElenent[@"modified_gmt"]];
self.post.featured_media=[NSString stringWithFormat: @"%@", jsonElenent[@"featured_media"]];
self.post.format=[NSString stringWithFormat: @"%@", jsonElenent[@"format"]];
self.post.links=[NSString stringWithFormat: @"%@", jsonElenent[@"links"]];
self.post.author=[NSString stringWithFormat: @"%@", jsonElenent[@"author"]];
self.post.content=[NSString stringWithFormat: @"%@", jsonElenent[@"content"]];
self.post.categories= [NSString stringWithFormat: @"%@", jsonElenent[@"category"]];
self.post.excerpt=[NSString stringWithFormat: @"%@", jsonElenent[@"excerpt"]];
@try {
NSFetchRequest *fetch = [[NSFetchRequest alloc] init];
NSString *s = jsonElenent[@"featured_media"];
NSManagedObjectContext *cxt = [self managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Media" inManagedObjectContext:cxt];
[fetch setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"id" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
fetch.sortDescriptors = sortDescriptors;
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"id = %@", [NSString stringWithFormat: @"%@", s]];
[fetch setPredicate:predicate];
NSArray *temp = [cxt executeFetchRequest:fetch error:nil];
for (Media *m in temp)
{
// m.posts=self.post.medias;
// self.post.medias=m.posts;
self.post.featured_media_link=m.source_url;
//m.posts=self.post;
// self.post.medias=m;
}
} @catch (NSException *exception) {
NSLog(@"%@", exception.reason);
} @finally {
NSLog(@"done");
}
NSError *error = nil;
if ([self.managedObjectContext hasChanges])
{
if (![self.managedObjectContext save:&error])
{
NSLog(@"Save Failed: %@", [error localizedDescription]);
}
else
{
NSLog(@"Save Succeeded");
}
}
});
}
dispatch_async(dispatch_get_main_queue(), ^{
[self.delegate itemsDownloaded];
});
}
@end
@interface MainTableViewController : UITableViewController<LokalModelProtocol,NSFetchedResultsControllerDelegate>
-(void)refreshTable;
@property (strong,nonatomic) UIRefreshControl* refCon;
@property (strong,nonatomic) NSMutableArray* arr;
@property (strong,nonatomic) LokalModel *lokal;
@property (strong,nonatomic) Media* media;
@property (strong,nonatomic) Post* post;
@property (strong,nonatomic) NSManagedObjectContext* managedObjectContext;
@property (strong,nonatomic) NSFetchedResultsController* fetchedResultsController;
@property (strong,nonatomic) NSPersistentStoreCoordinator* persistentStoreCoordinator;
@property (strong,nonatomic) NSString* type;
@end
@implementation MainTableViewController
@synthesize arr,refCon, lokal,managedObjectContext,fetchedResultsController,persistentStoreCoordinator,media,type,post;
-(NSManagedObjectContext *) managedObjectContext
{
return [(AppDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext];
}
-(void)refreshTable{
dispatch_async(dispatch_get_main_queue(), ^{
[self.refCon endRefreshing];
[self.tableView reloadData];
});
}
- (void)viewDidLoad {
[super viewDidLoad];
refCon = [[UIRefreshControl alloc]init];
[self.tableView addSubview:refCon];
[refCon addTarget:self action:@selector(refreshTable) forControlEvents:UIControlEventValueChanged];
arr = [[NSMutableArray alloc]init];
lokal = [[LokalModel alloc]init];
lokal.delegate=self;
[lokal downloadItems];
NSLog(@"reached viewdidload");
}
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear:animated];
[self refreshTable];
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
//#warning Incomplete implementation, return the number of sections
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
id<NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
NSLog(@"%lu", (unsigned long)[sectionInfo numberOfObjects]);
return [sectionInfo numberOfObjects];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 333.3f;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
ParallaxTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"mainCell" forIndexPath:indexPath];
self.post = [self.fetchedResultsController objectAtIndexPath:indexPath];
cell.titleLabel.text = [NSString stringWithFormat: @"%@", self.post.id];
[cell.parallaxImage sd_setImageWithURL:[NSURL URLWithString:post.featured_media_link]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]];
return cell;
}
-(void)mediaDownloaded {
NSLog(@"method called downloaded");
[self refreshTable];
}
-(void)itemsDownloaded {
NSError *error = nil;
if (![[self fetchedResultsController] performFetch:&error])
{
NSLog(@"error: %@", error);
abort();
}
[self refreshTable];
}
#pragma mark - Fetched Results Controller Section
-(NSFetchedResultsController*)fetchedResultsController
{
if (fetchedResultsController != nil)
{
return fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSManagedObjectContext *context = [self managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Post" inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"id" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
fetchRequest.sortDescriptors = sortDescriptors;
fetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:context sectionNameKeyPath:nil cacheName:nil];
fetchedResultsController.delegate = self;
return fetchedResultsController;
}
#pragma mark - Fetched Results Controller Delegates
- (void) controllerWillChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView beginUpdates];
}
-(void) controllerDidChangeContent:(NSFetchedResultsController *)controller
{
[self.tableView endUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath
{
UITableView *tableView = self.tableView;
switch (type)
{
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
{
Post *post = [self.fetchedResultsController objectAtIndexPath:indexPath];
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
cell.textLabel.text = post.title;
}
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void) controller:(NSFetchedResultsController *)controller didChangeSection:(id<NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
switch (type)
{
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationBottom];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationBottom];
break;
case NSFetchedResultsChangeMove:
break;
case NSFetchedResultsChangeUpdate:
break;
}
}
@end
Я должен описать свою модель данных, в основном я получаю данные из двух URL-адресов: один для постов и один дляМедиа, которые являются моими двумя объектами в моей модели CoreData.у них обоих есть уникальный идентификатор.сообщение имеет свойство featured_media, которое возвращает идентификатор связанного с ним носителя (я установил отношение «многие ко многим», но оно работает неправильно).так как я создаю объект post для каждого сообщения в массиве, я извлекаю связанный с ним носитель и сохраняю его URL-адрес в свойстве media_link в сущности Post.поэтому к этому времени методу cellForRowAtIndexPath требуется только один объект.но, опять же, он не будет показывать данные, пока я не буду с ним взаимодействовать.