I'm using a UICollectionView inside a UITableViewCell to show images inside a tableviewcell.
While downloading the photo in background the activity indicator should be animated en no image shown. Once the photo is downloaded the activity indicator should stop animating and the photo should be shown.
Everything works except for the first time the first cell is shown. The image is shown and the activity indicator keeps on animating. If I scroll the collectionView, it works for the other images and when I scroll back to the first image, it also works. It's only on the first time the first image is shown
The cell inside the collectionview is call PhotoCollectionView and the header looks like:
#interface PhotoCollectionCell : UICollectionViewCell
#property (strong, nonatomic) IBOutlet UIImageView *imageView;
#property (strong, nonatomic) IBOutlet UIActivityIndicatorView *activityIndicator;
#end
Code for cellForItemAtIndexPath
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"PhotoCollectionCell";
PhotoCollectionCell *cell = (PhotoCollectionCell *)[collectionView dequeueReusableCellWithReuseIdentifier:CellIdentifier forIndexPath:indexPath];
cell.imageView.image = nil;
UIImage *image = [thumbnails objectForKey:indexPath];
if(!image) {
[cell.activityIndicator startAnimating];
if (self.pictureCollectionView.dragging == NO && self.pictureCollectionView.decelerating == NO)
{
[self startDownload:images[indexPath.row] forIndexPath:indexPath];
}
} else {
[cell.activityIndicator stopAnimating];
cell.imageView.image = image;
}
return cell;
}
I tried several solutions given on the web, everything is executing on the main thread, so i don't know what to do anymore.
Help would be appreciated. Thanks in advance. Kind regards...
Related
i am working on uicollectionview. i want customize cell so i took separate class file for cell. i took an image in cell from storyboard. my problem is i want rounding image but image shape convert to be diamond. please suggest me the way to convert this diamond image into to circle.
see here
UICollectionView in storyboard
ViewController.h
#interface ViewController : UIViewController
#property(nonatomic, weak)IBOutlet UICollectionView *my_collectionview;
#end
ViewController.m
#interface ViewController ()
#end
#implementation ViewController
#synthesize my_collectionview;
- (void)viewDidLoad {
[super viewDidLoad];
}
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView{
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return 9;
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath{
CollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"CollectionViewCell" forIndexPath:indexPath];
return cell;
}
CollectionViewCell.h
#interface CollectionViewCell : UICollectionViewCell
#property(nonatomic, weak) IBOutlet UIImageView *temp_imgview;
#end
CollectionViewCell.m
-(void)awakeFromNib{
[temp_imgview.layer setCornerRadius:self.temp_imgview.frame.size.width/2];
temp_imgview.layer.borderWidth=0.5;
temp_imgview.layer.masksToBounds = YES;
temp_imgview.clipsToBounds=YES;
}
if i put hard code 100 instead of self.temp_imgview.frame.size.width/2 then it is working. can anybody help me how can i solve this
Depending on your constraints in the storyboard, the awakeFromNib might not be the correct place to all the rounded corners. That is because it might be that the frame of the imageView is not final there.
You could try adding the code for the rounded corners in layoutSubviews. Something like this:
- (void)layoutSubviews {
[super layoutSubviews];
[temp_imgview.layer setCornerRadius:self.temp_imgview.frame.size.width/2];
temp_imgview.layer.borderWidth=0.5;
temp_imgview.layer.masksToBounds = YES;
temp_imgview.clipsToBounds=YES;
}
Also, in your awakeFromNib, you missed the super call.
Let me know if this worked out for you or need more help! Good luck
Update
You could try using the size of the image, instead of the frame. Something like this:
- (void)layoutSubviews {
[super layoutSubviews];
[temp_imgview.layer setCornerRadius:self.temp_imgview.image.size.width/2];
temp_imgview.layer.borderWidth=0.5;
temp_imgview.layer.masksToBounds = YES;
temp_imgview.clipsToBounds=YES;
}
If this does not work either, try logging the frame of your image on iPhone and iPad to see what differs between them
Try adding [self layoutIfNeeded], it worked for me.
- (void)layoutSubviews {
[super layoutSubviews];
[self layoutIfNeeded];
imageView.layer.cornerRadius = CGRectGetWidth(imageView.bounds) / 2;
imageView.layer.borderWidth = 0.1;
imageView.clipsToBounds = YES;
}
To explain the issue, I had ViewControllerA with a UITableView called commentTableView inside of it. and from commentTableView i would segue to ViewControllerB but I needed to add an addition UITableView called mentionedFriendTable to ViewControllerA. But once i did add mentionFriendTable I started to have issues with the tables that caused the app to crash.
Issue Im Having
I decided to place commentTableView into a different class called justCommentsTable which is a UITableViewController class and add that class to ViewController. I have to place commentTableView in a different class and not mentionFriendTable because mentionFriendTable needs to be in ViewControllerA. and after a couple of hours I finally got that to work. but now that segue I initially had to ViewControllerB does not work, and crashes saying
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'Receiver (<justCommentsTable: 0x21032160>) has no segue with identifier 'segueToViewControllerB'
My Storyboard
On my storyboard i have ViewControllerA with a tableView inside of it and i linked up the tableview to #property (strong, nonatomic) IBOutlet UITableView *commentTable;
in the code below I explain how commentTable becomes the tableview from justCommentsTable
I know I'm getting this crash because ViewControllerB is connected to ViewControllerA through MainStoryboard.storyboard and not justCommentsTable
My Question
Is there a way to still segue ViewControllerA to ViewControllerB and pass data from commentTableView which is in a different class.
I'm gonna go ahead and place whatever code I find relevant to the issue. Just tell me if im missing any crucial code.
ViewControllerA.h
#import "justCommentsTable.h"
#interface ViewControllerA : UIViewController<UITableViewDelegate, UITableViewDataSource>{
// in justCommentsTable.m I add this controller to the view
justCommentsTable *commentsController;
}
// this is the table that is link up in storyboard
#property (strong, nonatomic) IBOutlet UITableView *commentTable;
//this is my mentions table that needs to be in ViewControllerA
#property (nonatomic, strong) UITableView *mentionTableView;
#end
ViewControllerA.m
- (void)viewDidLoad
{
[super viewDidLoad];
**// i set up the mentionTable here**
self.mentionTableView.transform = transform;
self.mentionTableView.delegate = self;
self.mentionTableView.dataSource = self;
self.mentionTableView.tag = 1;
[self.view addSubview:self.mentionTableView];
**// i set up the commentTable here**
if (commentsController == nil) {
commentsController = [[justCommentsTable alloc] init];
}
[commentTable setDataSource:commentsController];
[commentTable setDelegate:commentsController];
[commentsController setHomeUserID:homeUserID];
[commentsController setGetEventHostIDforNotif:getEventHostIDforNotif];
[commentsController setGeteventIDfrSEgue:geteventIDfrSEgue];
[commentsController setGetEVENTNamefrSegue:getEVENTNamefrSegue];
**// i set commentsController to the Tableview in justCommentsTable class**
commentsController.view = commentsController.tableView;
}
justCommentsTable.h
#interface justCommentsTable : UITableViewController<UITableViewDelegate, UITableViewDataSource,UITextFieldDelegate,UITextViewDelegate>
#end
justCommentsTable.m
#implementation justCommentsTable
//buttonTag is used for a button on the customCells
int buttonTag;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"commentCell";
customCell *cell =(customCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[customCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *commmentDict = [CommentArray objectAtIndex:indexPath.row];
NSString *commentText = [commmentDict objectForKey:#"comment"];
cell.textLabel.text = commentText;
// i need a custom button on the cells for other reasons
[cell.cellButton addTarget:self action:#selector(showButtonIndex:) forControlEvents:UIControlEventTouchUpInside];
return cell;
}
-(void)showButtonIndex:(UIButton*)button{
buttonTag = button.tag;
/*
buttonTag gets set here, and used in the prepareForSegue method
to find out what row the button was on.
*/
[self performSegueWithIdentifier:#"segueToViewControllerB" sender:self];
}
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
if ([segue.identifier isEqualToString:#"segueToViewControllerB"]){
//segue to profile from image button
ViewControllerB *VCB = segue.destinationViewController;
NSDictionary *commentDic = [CommentArray objectAtIndex:buttonTag];
/*
buttonTag was used to select the objectAtIndex
*/
NSString *commentTitle = [commentDic objectForKey:#"comment_title"];
VCB.title = commentTitle;
}
}
I know where my issue is, I just have no idea on how to fix it. and Ive searched for problems like mine, but I cant find one with a solid answer. if anyone can help, it would greatly be appreciated. thanks!
I use a UITableViewController to display the details of KoreanFood. The first cell is a custom UITableViewCell (OverviewCell) with an Image and two UITextFields, which I created and layout in Storyboard (AutoLayout).
I subclassed UITableviewCell like this:
// OverviewCell.h
#interface OverviewCell : UITableViewCell
#property (strong, nonatomic) IBOutlet UITextField *englishTitleTF;
#property (strong, nonatomic) IBOutlet UITextField *koreanTitleTF;
#property (strong, nonatomic) IBOutlet UIImageView *myImageView;
#property (strong, nonatomic) UIImage *thumbnail;
My textfields in Storyboard are set to enabled/UserInteractionenabled and the delegate is my TVC. When I create the cells I also do this in code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == GENERAL_SECTION) {
static NSString *overviewCellID = #"overviewCell";
OverviewCell *overviewCell = [tableView dequeueReusableCellWithIdentifier:overviewCellID forIndexPath:indexPath];
overviewCell.englishTitleTF.text = self.generalInfo.titleEnglish;
overviewCell.koreanTitleTF.text = self.generalInfo.titleKorean;
overviewCell.englishTitleTF.enabled = YES;
overviewCell.koreanTitleTF.enabled = NO;
//BOOL test = [overviewCell.englishTitleTF becomeFirstResponder];
overviewCell.koreanTitleTF.delegate = self;
overviewCell.englishTitleTF.delegate = self;
UIImageView *imageView = [[UIImageView alloc] initWithImage:self.generalInfo.thumbnail];
overviewCell.myImageView = imageView;
overviewCell.myImageView.frame = CGRectMake(25, 25, 95, 95);
[overviewCell addSubview:overviewCell.myImageView];
return overviewCell;
}
The comment with the BOOL is NO, and I just don't know why... As I set the text and it's displayed correctly, I know the Outlets are set and the Cell isn't nil (I checked that).
Why does this not become first responder?
I also tried some suggestions inside the OverviewCell subclass like the hit test or implementing the setSelected: / setEditing: methods. But a becomeFirstResponder to the textField here doesn't change anything as well.
A view can't become first responder until it's been added to the responder chain, which happens automatically when the view gets added as a subview of a view that's in a window in the application object's windows list. In other words, your cell hasn't been added to the table view yet, so it's not connected to anything, and hence can't become first responder.
Try sending becomeFirstResponder from a method that gets called after the table view has finished loading its cells. And of course, don't do this:
overviewCell.koreanTitleTF.enabled = NO;
I'm trying to create a custom UITableViewCell.
From XCode 4.6 interface builder, I've set the Style property of the cell to Custom. And added controls to the cell using drag and drop. 2 UILables and a UIButton. It looks like this.
I created a separate class deriving from UITableViewCell to assign the properties of the 3 UI elements and make the changes there. I've set the cell's custom class as DashboardCell from the Identity Inspector as well.
DashboardCell.h
#import <UIKit/UIKit.h>
#interface DashboardCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UILabel *numberOfMails;
#property (weak, nonatomic) IBOutlet UILabel *mailType;
#property (weak, nonatomic) IBOutlet UIButton *numberOfOverdueMails;
#end
DashboardCell.m
#import "DashboardCell.h"
#implementation DashboardCell
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[self.numberOfOverdueMails setBackgroundColor:[UIColor colorWithRed:244/255.0f green:119/255.0f blue:125/255.0f alpha:1.0f]];
[self.numberOfOverdueMails setTitle:#"lol" forState:UIControlStateNormal];
}
return self;
}
- (void)setSelected:(BOOL)selected animated:(BOOL)animated
{
[super setSelected:selected animated:animated];
// Configure the view for the selected state
}
#end
In the TableViewController, I have modified the following method to return my custom cell.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
DashboardCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[DashboardCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
return cell;
}
My problem is even though the custom button shows up, the changes I've done (changing the background color of the button, changing the title of one UILabel) aren't showing up. What seems to be the mistake here?
The method initWithStyle:reuseIdentifier: will not be called because you're using interface builder to create a cell.
You can set the background color and title by overriding the method awakeFromNib.
You can also set these in the method tableView:cellForRowAtIndexPath:
If you get your cell from a xib or storyboard, dequeueReusableCellWithIdentifier:forIndexPath: will always return a cell -- if one exists it will reuse it, if not it will create one from the template in IB. Therefore, your if(cell ==nil) clause will never be satisfied, and in fact is no longer needed. If you want to use an init method, then use initWithCoder:
Hi I have a tab tab controller and my first tab includes a view with:
3 text fields
a submit button
a tableView
Once I fill in the text fields I click submit and it adds the information to my managedObjectContext which is an sqlite database (CoreData).
As soon as I click submit I want the tableView to reload to include the added object. Currently my tableView will display the data in the database but it will only add the new row when I stop and re-run the simulator
This is the code for when the add button is tapped, it is here that I can't get the reload tableView working because it says tableView is an undeclared identifier, what have i missed?
-(IBAction)addButtonTapped:(id)sender {
NSLog (#"Add Button Tapped");
NSLog(#"Adding %# units of item code %# at $%# each",quantityTextField.text,productTextField.text,priceTextField.text);
Products_MarketAppDelegate* delegate = [[UIApplication sharedApplication] delegate];
NSManagedObjectContext* managedObjectContext = delegate.managedObjectContext;
NSManagedObject* newProduct;
newProduct = [NSEntityDescription insertNewObjectForEntityForName:#"Product" inManagedObjectContext:managedObjectContext];
[newProduct setValue:productTextField.text forKey:#"itemCode"];
[newProduct setValue:quantityTextField.text forKey:#"quantity"];
[newProduct setValue:priceTextField.text forKey:#"price"];
if ([managedObjectContext hasChanges])
NSLog(#"Managed Object Changed");
NSError* error;
[managedObjectContext save:&error];
// Insert Reload Table Code Here
// ** I have tried the following and it gives an error "Use of undeclared identifier 'tableView'"
//[tableView reloadData];
//[self.tableView reloadData];
}
As you can see below I have added the UITableViewDelegate & UITableViewDataSource in the header file. I have also hooked up the tableview in IB so that the delegate and datasource connections are linked to file's owner.
#import <UIKit/UIKit.h>
#import <CoreData/CoreData.h>
#interface FirstViewController : UIViewController
<UIApplicationDelegate, UITableViewDataSource,UITableViewDelegate,NSFetchedResultsControllerDelegate>
{
IBOutlet UITextField *productTextField;
IBOutlet UITextField *quantityTextField;
IBOutlet UITextField *priceTextField;
NSMutableArray *items;
NSFetchedResultsController *fetchedResultsController;
}
#property (nonatomic, retain) NSMutableArray *items;
#property (nonatomic, retain) NSFetchedResultsController *fetchedResultsController;
-(IBAction)addButtonTapped:(id)sender;
#end
This is the code to fill the tableView which works correctly
#pragma mark TableView
-(NSInteger)numberOfSectionsInTableView: (UITableView *)tableView {
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil){
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell
Product* productItem =[fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = [NSString stringWithFormat:#"%# x %# # $%#",productItem.quantity,productItem.itemCode,productItem.price];
return cell;
}
I have searched for answers on this site and on others but I must be doing something different and the solutions aren't helping me
Your UIViewController does not currently have an instance variable pointing to your tableview. Set one up:
#property (nonatomic, retain) IBOutlet UITableView *myTableView;
Remember to synthesize this in your .m
#synthesize myTableView;
Then in your code you can call
[self.myTableView reloadData];
You might have got confused by looking at code examples that use a UITableViewController instead of a UIViewController. The UITableViewController already has an instance variable called tableView, so your subclass wouldn't need it's own tableView instance variable declared. But you're using a UIViewController, so you must declare a tableView instance variable.
Thanks #MattyG for all your help. At first I wasn't sure if I was going against the norm and thats why it wasn't working.
I ended up solving the problem due to your suggestions & it works perfectly! I used the debugger and found that that although we had created a property for the table I had not created an IBOutlet and linked it in my nib file with:
IBOutlet UITableView *myTableView;
I guess this meant that I was telling myTableView to reload but it wasn't hooked up to my table and thus couldn't use the datasource methods.