Add more UICollectionViewCell to an existing UICollectionView - xcode

I'm trying to add some more cells to an existing UICollectionView, which is already filled with some cells.
I tried to use the CollectionView reloadData but it seems to reload the entire collectionView and I just wanted to add more cells.
Can anybody help me?

The UICollectionView class has methods to add/remove items. E.g., to insert an item at some index (in section 0), modify your model accordingly and then do:
int indexPath = [NSIndexPath indexPathForItem:index];
NSArray *indexPaths = [NSArray arrayWithObject:indexPath inSection:0];
[collectionView insertItemsAtIndexPaths:indexPaths];
The view will do the rest.

The easiest way to insert new cells to the UICollectionView without having to reload all its cell is by using the performBatchUpdates, which can be done easily by following the steps below.
// Lets assume you have some data coming from a NSURLConnection
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *erro)
{
// Parse the data to Json
NSMutableArray *newJson = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
// Variable used to say at which position you want to add the cells
int index;
// If you want to start adding before the previous content, like new Tweets on twitter
index = 0;
// If you want to start adding after the previous content, like reading older tweets on twitter
index = self.json.count;
// Create the indexes with a loop
NSMutableArray *indexes = [NSMutableArray array];
for (int i = index; i < json.count; i++)
{
[indexes addObject:[NSIndexPath indexPathForItem:i inSection:0]];
}
// Perform the updates
[self.collectionView performBatchUpdates:^{
//Insert the new data to your current data
[self.json addObjectsFromArray:newJson];
//Inser the new cells
[self.collectionView insertItemsAtIndexPaths:indexes];
} completion:nil];
}

Related

How to Reorder Cells Between Sections with NSFetchedResultsController

I have a table view that allows users to reorder cells between sections.
I have this, which works in a table with one section, but I can't figure out how to change this to work between sections...
-(void)tableView:(UITableView *)tableView
moveRowAtIndexPath:(NSIndexPath *)sourceIndexPath
toIndexPath:(NSIndexPath *)destinationIndexPath;
{
NSMutableArray *things = [[fetchedResultsController fetchedObjects] mutableCopy];
// Grab the item we're moving.
NSManagedObject *thing = [[self fetchedResultsController] objectAtIndexPath:sourceIndexPath];
// Remove the object we're moving from the array.
[things removeObject:thing];
// Now re-insert it at the destination.
[things insertObject:thing atIndex:[destinationIndexPath row]];
// All of the objects are now in their correct order. Update each
// object's displayOrder field by iterating through the array.
int i = 0;
for (NSManagedObject *mo in things)
{
[mo setValue:[NSNumber numberWithInt:i++] forKey:#"displayOrder"];
}
[managedObjectContext save:nil];
}
Please could anyone help?

Collectionview cells won't render with CKAsset

I'm no longer able to render collectionview cells after using data from Cloudkit via CKAssets. I was previously using images loaded in a folder on my desktop just for initial testing. I'm now using Cloudkit and I've created some test records via the CK dashboard using those same images. I was successfully able to query the CK database and retrieve the expected records. I then changed my code to populate the model data for the cells to use the CK data. That data previously came from the images retrieved locally. I can see from logging that I am getting the data from CK successfully, including the images. I can also see from logging that my custom CV cells are no longer getting initialed. From what I can tell, my code looks good based on examples I've seen online.
Can anyone help me with this? Thank you!
Designated initializer in the model...
- (instancetype)initImagesForSelection:(NSString *)selectionType {
self = [super init];
if (self) {
CKDatabase *publicDatabase = [[CKContainer defaultContainer] publicCloudDatabase];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"ImageDescription = 'description'"];
CKQuery *query = [[CKQuery alloc] initWithRecordType:#"ImageData" predicate:predicate];
[publicDatabase performQuery:query inZoneWithID:nil completionHandler:^(NSArray *results, NSError *error) {
// handle the error
if (error) {
NSLog(#"Error: there was an error querying the cloud... %#", error);
} else {
// any results?
if ([results count] > 0) {
NSLog(#"Success querying the cloud for %lu results!!!", (unsigned long)[results count]);
for (CKRecord *record in results) {
ImageData *imageData = [[ImageData alloc] init];
CKAsset *imageAsset = record[#"Image"];
imageData.imageURL = imageAsset.fileURL;
NSLog(#"asset URL: %#", imageData.imageURL);
imageData.imageName = record[#"ImageName"];
//imageData.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:imageAsset.fileURL]];
imageData.image = [UIImage imageWithContentsOfFile:imageAsset.fileURL.path];
NSLog(#"image size height:%f, width:%f", imageData.image.size.height, imageData.image.size.width);
[self.imageDataArray addObject:imageData];
}
NSLog(#"imageDataArray size %lu", (unsigned long)[self.imageDataArray count]);
}
}
}];
}
return self;
}
Collectionview viewcontroller which worked perfectly before pulling the data from Cloudkit...
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell"; // string value identifier for cell reuse
ImageViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
NSLog(#"cellForItemAtIndexPath: section:%ld row:%ld", (long)indexPath.section, (long)indexPath.row);
cell.layer.borderWidth = 1.0;
cell.layer.borderColor = [UIColor grayColor].CGColor;
ImageData *imageData = [self.imageLoadManager imageDataForCell:indexPath.row];
cell.imageView.image = imageData.image;
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
return cell;
}
Ok, I figured this out. My code was actually working. The collectionview was not displaying due to a multithreading/asynchronous download issue with the data from cloudkit. I hit the camera button to take a pic, which refreshed the CV and everything in the CV appeared. I just need to use multithreading so things start rendering while the images are downloading.

How to make dynamically adding of rows when user reached to the last row of the NStableView?

I have a NSTableview which shows 50 rows currently which is fixed static. Now I want to add a feature into it. I want to add a more 50 rows to the table when user reach to the last row of the NSTableView. I mean currently I am showing fixed 50 rows in the application.
But now I want to add 50 more rows whenever user reaches to the last row of previous NsTableview.
Please give me any suggestions or any sample code to achieve my motive. Thanks in advance.
What i have done is(This code does not work with row selected(Down key pressed), and does not load new rows) -
-(void)awakeFromNib{
for(int i=0;i<25;i++)
[_list addObject:[[Person alloc] init]];
[_tableView reloadData];
[NSNotificationCenter.defaultCenter addObserver:self selector:#selector(scrollViewDidScroll:) name:NSViewBoundsDidChangeNotification object:[[_tableView enclosingScrollView] contentView]];
}
-(void) doSomething{
Person *p = [[Person alloc] init];
static int i =1;
NSString *string = [NSString stringWithFormat:#"John%i",i];
[p setName:string];
for(int i=0;i<25;i++)
[_list addObject:p];
// Need to use reloadDataForRowIndexes:columnIndexes: anyone please help me with this.
[_tableView reloadData];
i++;
}
- (void)scrollViewDidScroll:(NSNotification *)notification {
NSScrollView *scrollView = [notification object];
// Test if bottom of content view is reached.
CGFloat currentPosition = CGRectGetMaxY([scrollView visibleRect]);
CGFloat tableViewHeight = [self.tableView bounds].size.height;
if (currentPosition > tableViewHeight) {
// YOUR ACTION
[self doSomething];
}

Nested NSCollection View

I am trying to create a nested collection view. First I did for one level.
Created a data model class with String header. In app delegate created an array sectionTitle. Now in the nib, I added collection view & array controller and did all the bindings following this guide. Next in awakeFromNib I populated some random data
- (void)awakeFromNib {
int idx = 0;
NSMutableArray *sectionTitle = [[NSMutableArray alloc] init];
while (idx < 1) {
HeaderModel *header = [[HeaderModel alloc] init];
[header setHeader:[NSString stringWithFormat:#"Section %d", idx]];
[sectionTitle addObject:header];
idx++;
}
[self setHeaderData:sectionTitle];
}
Running it will give me 4 sections. I want to achieve similar layout as this. Section title, under it another collection of items. The answer given there only hints at using Nested collection view.
So I added another collection view in the first view prototype. Then I followed the same approach what I did for the first view(with different data model and array).
- (void)awakeFromNib {
int idx = 0;
NSMutableArray *sectionTitle = [[NSMutableArray alloc] init];
NSMutableArray *groupData = [[NSMutableArray alloc] init];
while (idx < 1) {
HeaderModel *header = [[HeaderModel alloc] init];
DataModel *name = [[DataModel alloc] init];
[header setHeader:[NSString stringWithFormat:#"Section %d", idx]];
[name setName:[NSString stringWithFormat:#"Name %d", idx]];
[sectionTitle addObject:header];
[groupData addObject:name];
idx++;
}
[self setHeaderData:sectionTitle];
[self setData:groupData]; //NSCollectionView item prototype must not be nil.
}
But now I get the error NSCollectionView item prototype must not be nil.
How do I resolve this ?
I have just answered a similar question here
But somehow by inserting the second NSCollectionView with I.B, you get a corrupted prototype for your inner NSCollectionViewItem. Simply try to extract each associated NSView into its own .xib

Retrieving the data from the table in iphone

I have a table wherein every row contains a textfield.After i entertext in all the rows which are text fields i want to retrieve the data into an array.Can any one tell me the idea of retrieving the data from every row which are textfields?
I cannot believe you. Bad grammar and no research.
To get an array of all text fields, I would do:
NSArray *subviews = self.view.subviews;
NSMutableArray *textFelds = [[NSMutableArray alloc]init];
NSMutableArray *indexPaths = [[NSMutableArray alloc]init];
NSObject *obj;
for (obj in subviews) {
if ([obj class] == [UITextField class]) {
[textFields addObject:obj];
CGPoint location = obj.center;
    NSIndexPath *indexPath = [self.tableView indexPathForRowAtPoint:location];
[indexPaths addObject:indexPath];
}
}
It first gets all of the subviews of the main view, then determines if they are text fields. If they are textFields, it adds that to an array and also gets the indexPath.
I hope I have answered your question
You are having the details like, which row has text fields, which are not.
You can get this feature by using two different king of cells
static NSString *CellIdentifierNormal = #"Cell";
static NSString *CellIdentifierTF = #"Cell";
UITableViewCell *cell;
if(indexPath.row %2 == 0){ //Example
cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifierNormal];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifierNormal] autorelease];
}
} else {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifierTF] autorelease];
TF *tf = [[TF alloc] init];
tf.tag = 10;
}
In Text field row case, should not use the dequeueReusableCellWithIdentifier it re uses the existing cells, so that the text fields data may corrupt [This will happen when your data rows size greater than the table size - height]
Whenever you want collect the data from TF's
Just run loop with number of rows in table, and check same condition as you are using in creating cell.
Access the cell, and TF from cell by using tag number [10] from TF get the text

Resources