New to IOS and objective C and been doing several tutorials, with adding buttons, textfields etc. Been looking alot on stackoverflow, which has been very helpful :) Now I am trying to create a collectionview within a frame and then put a button below it. I can get a button to show up, and the top half of the screen where I have defined the collection to appear turns black, while the rest goes white, as intended. Currently the collection should come up with a label telling me the cell number, so very basic. Not sure if I'm setting up my views wrong, or if there is something wrong with my CellViews.
I have created a mainView controller, where I have defined my button and collection view, like this:
MainViewController.h:
#interface MainViewController : UIViewController <UICollectionViewDataSource, UICollectionViewDelegateFlowLayout>
#property(nonatomic, strong) IBOutlet UICollectionView *collectionView;
#property(nonatomic, strong) IBOutlet UIButton *diaryButton;
- (id)init;
My .m looks like this:
#implementation MainViewController
#synthesize collectionView;
#synthesize diaryButton;
- (id) init {
self = [super init];
if (self) {
CGRect buttonFrame = CGRectMake(10, 250, 70, 30);
diaryButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[diaryButton setFrame:buttonFrame];
[diaryButton setTitle:#"Diary" forState:UIControlStateNormal];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(64.0, 64.0);
layout.minimumInteritemSpacing = 4;
layout.minimumLineSpacing = 4;
layout.scrollDirection = UICollectionViewScrollPositionCenteredVertically;
layout.sectionInset = UIEdgeInsetsMake(2.0, 2.0, 2.0, 2.0);
CGRect collectionFrame = CGRectMake(0, 0, 320, 200);
collectionView = [[UICollectionView alloc] initWithFrame:collectionFrame collectionViewLayout:layout];
[self.view addSubview:collectionView];
[self.view addSubview:diaryButton];
//[self.view setBackgroundColor:[UIColor blueColor]];
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"ID"];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 30;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"ID" forIndexPath:indexPath];
UILabel *label = [[UILabel alloc] initWithFrame:cell.bounds];
label.textAlignment = NSTextAlignmentCenter;
label.text = [NSString stringWithFormat:#"%d", indexPath.row];
[cell.contentView addSubview:label];
return cell;
}
/////////////////////////////////////////////////////////////////////////////////
// collection view delegate methods ////////////////////////////////////////
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"cell #%d was selected", indexPath.row);
}
My appdelegate looks like this:
#synthesize mainVC;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.mainVC = [[MainViewController alloc] init];
[self.window addSubview:mainVC.view];
//self.window.rootViewController = mainVC;
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
Any help will be greatly appreciated.
I don't know exactly why your collection isn't showing anything, but you're missing the numberOfSectionsInCollectionView: method from the UICollectionViewDataSource. The collection view might be assuming that the number of sections is 0.
http://developer.apple.com/library/ios/#documentation/uikit/reference/UICollectionViewDataSource_protocol/Reference/Reference.html
Also, did you set the datasource and delegate to self for your UICollectionView?
Related
If I use this code to indent from left, everything is indented (separator + content)
table.contentInset = UIEdgeInsetsMake(0, 20, 0, 0);
Same if I use this:
cell.layoutMargins = UIEdgeInsetsMake(0, 20, 0, 0);
This doesn't help neither, because it doesn't move the image.
cell.indentationLevel = 10;
You can use a CustomTableCell to get what you want:
At first, in ViewController:
#import "ViewController.h"
#import "MyTableCell.h"
#interface ViewController ()
#property UITableView *tableView;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)];
_tableView.separatorStyle = UITableViewCellSelectionStyleNone;
_tableView.backgroundColor = [UIColor grayColor];
_tableView.dataSource = self;
_tableView.delegate = self;
[self.view addSubview:_tableView];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 20;
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
MyTableCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MyCell"];
if (nil == cell) {
cell = [[MyTableCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"MyCell"];
}
//Update data for cell
return cell;
}
#end
This is MyTableCell.h:
#import "MyTableCell.h"
#interface MyTableCell()
#property UIView *containerView;
#property UIView *separationLine;
#end
#implementation MyTableCell
-(id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
_containerView = [[UIView alloc] init];
_containerView.backgroundColor = [UIColor redColor];
[self addSubview:_containerView];
_separationLine = [[UIView alloc] init];
_separationLine.backgroundColor = [UIColor blackColor];
[self addSubview:_separationLine];
return self;
}
-(void)layoutSubviews{
_containerView.frame = CGRectMake(20, 0, self.frame.size.width-20, self.frame.size.height-1);
_separationLine.frame = CGRectMake(10, self.frame.size.height-1, self.frame.size.width-10, 1);
}
#end
And this is the screenshot for the code:
You can modify the code in "layoutSubviews" as your wish.
Hope it can help you.
I am having a hard time figuring out why cell.imageview property doesn't show me image below. UIImage is not nil, cells are created, if I assign a background to cell, it is displayed which proves I am creating collectionview and my cells correctly. I programmatically create my collectionview and don't use any IB or interface builder. I have done this lots of times before, but I am really scratching my head with this one.
Thanks in advance.
#interface MainViewController : UIViewController
#property(strong, nonatomic) UICollectionView *collectionView;
#end
#interface MainViewController ()<
UICollectionViewDataSource, UICollectionViewDelegate,
UICollectionViewDelegateFlowLayout, UIGestureRecognizerDelegate>
#property(nonatomic, strong) MHTransitionShowDetail *interactivePushTransition;
#property(nonatomic) CGPoint lastPoint;
#property(nonatomic) CGFloat startScale;
#property(strong, nonatomic) NSMutableArray *carImages;
#end
#implementation MainViewController
- (instancetype)init {
self = [super init];
if (self) {
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_carImages = [#[
#"chevy_small",
#"mini_small",
#"rover_small",
#"smart_small",
#"highlander_small",
#"venza_small",
#"volvo_small",
#"vw_small",
#"ford_small",
#"nissan_small"
] mutableCopy];
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UICollectionViewFlowLayout *layout =
[[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(106, 106);
layout.minimumLineSpacing = 1.0;
layout.minimumInteritemSpacing = 1.0;
self.collectionView = [[UICollectionView alloc] initWithFrame:self.view.frame
collectionViewLayout:layout];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
self.collectionView.alwaysBounceVertical = YES;
[self.collectionView setContentInset:UIEdgeInsetsMake(20, 10, 10, 10)];
[self.collectionView registerClass:[IKGCollectionViewCell class]
forCellWithReuseIdentifier:#"myCell"];
self.collectionView.backgroundColor = [UIColor whiteColor];
[self.view addSubview:self.collectionView];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma CollectionView & FlowLayout methods
- (CGSize)collectionView:(UICollectionView *)collectionView
layout:(UICollectionViewLayout *)collectionViewLayout
sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(120, 120);
}
- (NSInteger)collectionView:(UICollectionView *)collectionView
numberOfItemsInSection:(NSInteger)section {
return self.carImages.count;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
IKGCollectionViewCell *cell =
[collectionView dequeueReusableCellWithReuseIdentifier:#"myCell"
forIndexPath:indexPath];
long row = [indexPath row];
UIImage *image = [UIImage imageNamed:self.carImages[row]];
cell.imageView.userInteractionEnabled = YES;
cell.imageView.image = image;
NSLog(#"cell.image view %#", image);
// [self makeCell:(IKGCollectionViewCell *)cell atIndexPath:indexPath];
return cell;
}
}
#end
#interface IKGCollectionViewCell : UICollectionViewCell
#property(nonatomic, strong) UIImageView *imageView;
#end
#implementation IKGCollectionViewCell
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.imageView = [[UIImageView alloc] initWithFrame:self.bounds];
NSLog(#"self.bounds is %#", NSStringFromCGRect(self.bounds));
}
return self;
}
- (void)layoutSubviews {
[super layoutSubviews];
self.imageView.frame = self.contentView.bounds;
}
#end
You missed to add the cell's imageView as a it's subview.
So in cell's initWithFrame
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
self.imageView = [[UIImageView alloc] initWithFrame:self.bounds];
//Add imageView as subview
[self addSubview:self.imageView];
NSLog(#"self.bounds is %#", NSStringFromCGRect(self.bounds));
}
return self;
}
I am currently working on writing a UICollectionViewController to load images from a server and put the images into custom UICollectionViewCells within a UICollectionView. To make things simpler than it already is, I don't pull from a database, I just simply create an array of images that are stored locally. It works but for some reason, not all of the cells show the image until I start scrolling.
Heres an image of whats going on!
Image
I have read up on a few tutorials but they all use storyboard... I am wanting to write this programmatically.
Heres some code:
AppDelegate.m:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
JSMediaCollectionController *instagram = [[JSMediaCollectionController alloc] initWithCollectionViewLayout:[UICollectionViewFlowLayout new]];
instagram.datasource = self;
self.array = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
[self.array addObject:#"instant_noodle_with_egg.jpg"];
}
UINavigationController *navCon = [[UINavigationController alloc] initWithRootViewController:instagram];
self.window.rootViewController = navCon;
[self.window makeKeyAndVisible];
return YES;
}
- (NSArray *)itemsToLoad
{
return [NSArray arrayWithArray:self.array];
}
JSMediaController.m
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = NO;
// Register cell classes
[self.collectionView registerClass:[JSMediaCollectionCell class] forCellWithReuseIdentifier:reuseIdentifier];
self.showOneItemPerRow = false;
// Do any additional setup after loading the view.
}
#pragma mark <UICollectionViewDataSource>
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [[self.datasource itemsToLoad] count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
JSMediaCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:reuseIdentifier forIndexPath:indexPath];
[cell setImage:[UIImage imageNamed:[[self.datasource itemsToLoad] objectAtIndex:indexPath.row]]];
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:#"photo-frame.png"]];
return cell;
}
...
...
JSMediaCell.m:
#interface JSMediaCollectionCell()
#property (nonatomic) UIImageView *view;
#end
#implementation JSMediaCollectionCell
- (id)initWithFrame:(CGRect)frame
{
if (!(self = [super initWithFrame:frame])) return nil;
self.view = [[UIImageView alloc] initWithFrame:self.frame];
[self.viewForBaselineLayout addSubview:self.view];
return self;
}
- (void)setImage:(UIImage *)image
{
self.view.image = image;
}
I greatly appreciate anyones help in getting me on the right track... Just as a reminder... As I start scrolling, the images are reloaded, but not all the cells have an image loaded in the subview... just some.
I can see that you are initialising the view property in the cell file with self.frame.
Instead, it should be
self.view = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, self.frame.size.width, self.frame.size.height)];
I think you can guess what went wrong.!!!
The frame should be wrt to the cell.
When the subview is added to cell, it takes the values of the origin of the cell, so it goes out of cell's view
I have a view controller (that sits in a tab bar controller), but need to add a collection view to that controller. I see lots of tutorials on google but they all seem to point to creating a UICollectionViewController and starting in viewDidLoad. But how do I do it in a subview?
I have my view controller.m file like so:
- (void) createView // called from viewDidLoad
{
UIScrollView *scrollView = [[UIScrollView alloc] initWithFrame:CGRectMake(0.0, 64.0, screenWidth, screenHeight)];
[scrollView.layer addGradient];
ACollectionView *theview = [[ACollectionView alloc] init];
[self.view addSubview:theview];
}
Next I started a UICollectionView subclass called ACollectionView.h
#interface ACollectionView : UICollectionView
#end
And the .m file is this:
#import "ACollectionView.h"
#implementation BestCollectionView
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
}
return self;
}
Where do I start the collection view, in the initWithFrame?
I am trying to follow this:
Creating a UICollectionView programmatically
Is my paradigm correct?
#property (nonatomic, strong) UICollectionView *collectionView;
- (void)viewDidLoad
{
[super viewDidLoad];
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
self.collectionView = [[UICollectionView alloc] initWithFrame:self.yourSubview.frame collectionViewLayout:layout];
[self.collectionView setDataSource:self];
[self.collectionView setDelegate:self];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[self.yourSubview addSubview:self.collectionView];
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 50;
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
cell.backgroundColor = [UIColor redColor];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(100, 100);
}
I'm trying to add a uicollectionview as a subview into a View, called CollectionSpace, by calling it from Storyboard.
UIViewController *CollectionVC =[self.storyboard instantiateViewControllerWithIdentifier:#"CollectionVC"];
CollectionVC.view.frame = CGRectMake(CollectionSpace.frame.origin.x-276, CollectionSpace.frame.origin.y-87, CollectionSpace.frame.size.width+2, CollectionSpace.frame.size.height-2);
[CollectionSpace addSubview:CollectionVC.view];
The storyboard has a Collection View where the delegate and Source, as the uicollectionview have been linked to the owner view controller. Here is the code:
#import "ViewController.h"
#interface ViewController ()
#property (nonatomic, strong) IBOutlet UICollectionView *collectionView; //linked
#end
#implementation ViewController
- (void)viewDidLoad
{
self.view = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
UICollectionViewFlowLayout *layout=[[UICollectionViewFlowLayout alloc] init];
_collectionView=[[UICollectionView alloc] initWithFrame:self.view.frame collectionViewLayout:layout];
[_collectionView setDataSource:self];
[_collectionView setDelegate:self];
[_collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:#"cellIdentifier"];
[_collectionView setBackgroundColor:[UIColor redColor]];
[self.view addSubview:_collectionView];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return 100;
}
// The cell that is returned must be retrieved from a call to -dequeueReusableCellWithReuseIdentifier:forIndexPath:
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
UICollectionViewCell *cell=[collectionView dequeueReusableCellWithReuseIdentifier:#"cellIdentifier" forIndexPath:indexPath];
cell.backgroundColor=[UIColor greenColor];
return cell;
}
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout*)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath
{
return CGSizeMake(150, 150);
}
So this works fine, it loads the uicollectionview and I can see the cells. The problem comes when I scroll. Once I scroll, the app crashes. (lldb)
I tried to call differently by importing the view controller and initiate it like this:
UICollectionViewFlowLayout *aFlowLayout = [[UICollectionViewFlowLayout alloc] init];
[aFlowLayout setItemSize:CGSizeMake(200, 140)];
[aFlowLayout setScrollDirection:UICollectionViewScrollDirectionHorizontal];
ViewController *CollectionVC = [[ViewController alloc]initWithCollectionViewLayout:aFlowLayout];
But the uicollectionview doesn't show up.
Any idea what could be causing the crash?