【问题标题】:How to implement endless loading in table or collection view?如何在表格或集合视图中实现无限加载?
【发布时间】:2014-10-25 09:55:36
【问题描述】:

我正在构建一个文章阅读应用程序。我正在从 JSON 链接获取数据,例如 uitableview 中的文章图片和标题。

我无法在 uitableview 中实现分页,假设我的 JSON 链接是 www.example.com&page=1 一次包含 10 篇文章,即 1-10。

当我在像 www.example.com&page=2 这样的 JSON 链接中连接以获得 11-20 篇文章列表时。

我无法实现如何在滚动时在 uitableview 中加载数据并使用数据增加行数。

这是我的代码:

     int *x=1;
    int *inc=10;

    @interface ysTableViewController ()

    {
     Reachability *internetReachable;
     }
     @end

      @implementation ysTableViewController

    - (id)initWithStyle:(UITableViewStyle)style
  {
         self = [super initWithStyle:style];
        if (self) {
    // Custom initialization
        }
      return self;
   }

    - (void)viewDidLoad
    {
       [super viewDidLoad];
        [self checkInternetConnection];
       UILabel *titleLabel = [[UILabel alloc] initWithFrame:CGRectMake(20,10,0,20)];
       titleLabel.textColor = [UIColor blackColor];
       titleLabel.backgroundColor = [UIColor clearColor];
       titleLabel.text = @"Story";
     [self.navigationItem setTitleView:titleLabel];


         }

  - (void)scrollViewDidScroll:(UIScrollView *)aScrollView {

    CGPoint offset = aScrollView.contentOffset;

   CGRect bounds = aScrollView.bounds;

   CGSize size = aScrollView.contentSize;

    UIEdgeInsets inset = aScrollView.contentInset;

    float y = offset.y + bounds.size.height - inset.bottom;

   float h = size.height;

    float reload_distance = 10;

     if(y > h + reload_distance) {

      NSLog(@"load more rows");

       inc=inc+10;

      BOOL myBool = [self isNetworkAvailable];

       if (myBool)

    {

        @try {

            // for table cell seperator line color

            self.tableView.separatorColor = [UIColor colorWithRed:190/255.0 green:190/255.0 blue:190/255.0 alpha:1.0];

            // for displaying the previous screen lable with back button in details view controller

            UIBarButtonItem *backbutton1 = [[UIBarButtonItem alloc] initWithTitle:@"" style:UIBarButtonItemStyleBordered target:nil action:nil];

           [[self navigationItem] setBackBarButtonItem:backbutton1];

             _Title1 = [[NSMutableArray alloc] init];

            _Author1 = [[NSMutableArray alloc] init];

            _Images1 = [[NSMutableArray alloc] init];

            _Details1 = [[NSMutableArray alloc] init];

            _link1 = [[NSMutableArray alloc] init];

            _Date1 = [[NSMutableArray alloc] init];

             NSString *urlString=[NSString stringWithFormat:@“www.example.com&page=%d",x];

            NSLog(@"xxxxx===%d",x);

           NSURL *newUrl=[NSURL URLWithString:urlString];

             NSData* data = [NSData dataWithContentsOfURL:newUrl];

            NSArray *ys_avatars = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

             x++;

          if(ys_avatars){

            for (int j=0;j<ys_avatars.count;j++)

                {

                    [_Title1 addObject:ys_avatars[j][@"title"]];

                    [_Author1 addObject: ys_avatars[j][@"author"]];

                    [_Images1 addObject: ys_avatars[j][@"featured_img"]];

                    [_Details1 addObject:ys_avatars[j][@"content"]];

                    [_link1 addObject:ys_avatars[j][@"permalink"]];

                    NSString *newStr=[ys_avatars[j][@"date"] substringToIndex:[ys_avatars[j][@"date"] length]-3];

                    [_Date1 addObject:newStr];

                }        }

            else

            {

                NSLog(@"asd");

                  }    }

           @catch (NSException *exception) {

           }        

         }

      }

   }

       - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

      {

// Return the number of sections.

      return 1;

     }

      - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section

    {

// Return the number of rows in the section.

      return inc;

         }

          - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath

       {

       static NSString *Cellidentifier1 = @"ysTableViewCell";

         ysTableViewCell *cell1 = [tableView dequeueReusableCellWithIdentifier:Cellidentifier1 forIndexPath:indexPath];

          // Configure the cell...

        long row = [indexPath row];

         cell1.TitleLabel1.text = _Title1[row];

         cell1.AuthorLabel1.text = _Author1[row];

             NSString *yourStoryUrl = [_Images1[indexPath.row] stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding];

      if(yourStoryUrl) {

            NSArray *subStringsUrl = [yourStoryUrl componentsSeparatedByString:@"/"];

         NSString *stripedName = [subStringsUrl lastObject];

         NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

        NSString *documentsDirectory = [paths objectAtIndex:0];

    //Local stored image file path

           NSString* filePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@",stripedName]];

           if(filePath) {

            UIImage *image = [UIImage imageWithContentsOfFile:filePath];

             if(image) {

            // Now the image will have been loaded and decoded and is ready to rock for the main thread

                ysTableViewCell  *updateCell =(id)[tableView cellForRowAtIndexPath:indexPath];

                if(updateCell)

                    updateCell.ThumbImage1.image=image;

                cell1.ThumbImage1.image=image;

          } else {

            dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

            dispatch_async(taskQ, ^{

                NSURL *Imageurl = [NSURL URLWithString:yourStoryUrl];

                NSData *data =  [NSData dataWithContentsOfURL:Imageurl];

                UIImage *images1 = [[UIImage alloc] initWithData:data];

              NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

                NSString *documentsDirectory = [paths objectAtIndex:0];

                NSData *imageData = UIImagePNGRepresentation(images1);

                //_imagePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png",stripedName]];



                // NSLog((@"pre writing to file"));

                if (![imageData writeToFile:filePath atomically:NO])

                {

                    NSLog((@"Failed to cache image data to disk"));

                }

                else

                {

                    NSLog((@"the cachedImagedPath is %@",filePath));

                }

                // Now the image will have been loaded and decoded and is ready to rock for the main thread

                dispatch_sync(dispatch_get_main_queue(), ^{

                    ysTableViewCell  *updateCell =(id)[tableView cellForRowAtIndexPath:indexPath];

                    if(updateCell)

                        updateCell.ThumbImage1.image=images1;

                    cell1.ThumbImage1.image=images1;

                });

                  });

        }



    } else {

        dispatch_queue_t taskQ = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

        dispatch_async(taskQ, ^{

            NSURL *Imageurl = [NSURL URLWithString:yourStoryUrl];

            NSData *data =  [NSData dataWithContentsOfURL:Imageurl];

            UIImage *images1 = [[UIImage alloc] initWithData:data];

            //        NSString *myString = [Imageurl absoluteString];

            //        NSLog(@"%@",myString);

            NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);

            NSString *documentsDirectory = [paths objectAtIndex:0];



             NSData *imageData = UIImagePNGRepresentation(images1);

             _imagePath =[documentsDirectory stringByAppendingPathComponent:[NSString stringWithFormat:@"%@.png",stripedName]];



            // NSLog((@"pre writing to file"));

            if (![imageData writeToFile:_imagePath atomically:NO])

            {

                NSLog((@"Failed to cache image data to disk"));

            }

            else

            {

              //  NSLog((@"the cachedImagedPath is %@",_imagePath));

            }

         // Now the image will have been loaded and decoded and is ready to rock for the main thread

              dispatch_sync(dispatch_get_main_queue(), ^{

                 ysTableViewCell  *updateCell =(id)[tableView           cellForRowAtIndexPath:indexPath];

                if(updateCell)

                    updateCell.ThumbImage1.image=images1;

                cell1.ThumbImage1.image=images1;

            });

           });

    }

}

return cell1;

  }

【问题讨论】:

  • 注意 - 您的代码太长了。你绝对必须把它分解成更小的部分。每当您有一段超过 3 行的代码时,请将其设为单独的函数。几乎不可能“阅读”并按原样帮助您的代码 - 希望它有所帮助!

标签: ios objective-c json uitableview pagination


【解决方案1】:

这绝非易事。一般而言,您需要看起来像这样的代码..

请注意这个基本例程的四个非常不同的部分。

我从来没有为这个问题找到一个有效的“通用”包解决方案。

再一次,看看这里的“四个部分”:它们给出了你正在寻找的逻辑!

-(void)forTerm:(NSString *)term doPageAfter:(int)doingThisPage
  {

  doingThisPage = doingThisPage + 1;
  if ( doingThisPage > 20 ) return; // never, ever, ever forget that!! heh.

  [CLOUD search:term page:doingThisPage then:^(NSArray *thoseTenResults)
    {




    self.searchSpinner.hidden = YES;

    // (step 1) IF IT IS "PAGE 1", we need to re-kick-off the array...
    if ( doingThisPage == 1 )
      CLOUD.searchResultsRA = [[NSMutableArray alloc] init];




    // (step 2) go ahead and add on these results

    if ( doingThisPage == 1 )
      {
      [CLOUD.searchResultsRA addObjectsFromArray:thoseTenResults];
      [self.searchDisplay safelyReloadBouncyTable];
      }
    else
      {
      [self.searchDisplay.collectionView performBatchUpdates:^
        {
        NSUInteger oldSize = CLOUD.searchResultsRA.count;
        [CLOUD.searchResultsRA addObjectsFromArray:thoseTenResults];
        NSUInteger newSize = CLOUD.searchResultsRA.count;

        NSMutableArray *arrayWithIndexPaths = [NSMutableArray array];
        for (NSUInteger i = oldSize; i < newSize; i++)
          [arrayWithIndexPaths
              addObject:[NSIndexPath indexPathForRow:i inSection:0]];

        [self.searchDisplay justSignal];
        [self.searchDisplay.collectionView
           insertItemsAtIndexPaths:arrayWithIndexPaths];
        }
        completion:nil];
      }




    // (step 3) indeed if it's the first page, do a drop-in for fun
    if ( doingThisPage == 1 ) [self.searchDisplay.view dropIn:nil];
    // (for a "new search" which is now being displayed, in your UX
    // there would be some sort of indication of that fact - do it here)




    // (step 4) IF there WERE results .. try another page!
    if ( thoseTenResults.count > 0 )
      [self forTerm:term doPageAfter:doingThisPage];
      // note we are calling this same routine, again!!!
    }
    ];
  }

【讨论】:

  • @Joe 谢谢,你能解释一下这是为了什么吗:[CLOUD search:term page:doingThisPage then:^(NSArray *thoseTenResults)
  • 您好,Joe,能否将您找到的文章网址发给我...谢谢!
  • 你好 Joe Blow,是的,我知道 iOS 中的 UIWebView。事实上,我们使用 UIWebView 来显示文章。
猜你喜欢
  • 2018-07-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-06-02
  • 2017-11-21
  • 1970-01-01
  • 1970-01-01
  • 2018-07-23
相关资源
最近更新 更多