I am trying to implement a UICollectionView inside a UIView, but I cant find out how to do it. There is a lot of tutorials on how to use UICollectionView with a UICollectionViewController, but not how to implement one in a regular View.
How do you do that?
1) Drag a UICollectionView into your UIView and size it appropriately.
2) Create a property which is also an IBOutlet in your .h file for the collection view:
#property (nonatomic, retain) IBOutlet UICollectionView *myCollectionView;
3) Again in your .h file declare your delegates, so now your .h should look somethng like this:
#interface UtaQuickView : UIViewController <UICollectionViewDataSource, UICollectionViewDelegate> {
}
#property (nonatomic, retain) IBOutlet UICollectionView *myCollectionView;
4) Connect your myCollectionView IBOutlet in your storyboard.
5) (optional) If you're targeting anything older than iOS6 synthesize your myCollectionView property. If you're targeting iOS6, it will auto-synthesize it for you. This goes for all properties, not just UICollectionViews. So in iOS6, you don't need to #synthesize myCollectionView = _myCollectionView at all. You can just use _mycollectionview wherever you need to access the property.
6) In your .m file viewDidLoad, set your delegate and dataSource.
_myCollectionView.delegate = self;
_myCollectionView.dataSource = self;
7) Implement the required dataSource methods:
#pragma mark - UICollectionView DataSource
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
From there you can implement as many or as little of the UICollectionViewDelegate methods as you need. However, 2 are required according to the documentation:
#pragma mark - UICollectionViewDelegate
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingCell:(UICollectionViewCell *)cell forItemAtIndexPath:(NSIndexPath *)indexPath
- (void)collectionView:(UICollectionView *)collectionView didEndDisplayingSupplementaryView:(UICollectionReusableView *)view forElementOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
It's important to note that you can substitute <UICollectionViewDelegateFlowLayout> for <UICollectionViewDelegate> and still have access to all of the methods in <UICollectionViewDelegate> because <UICollectionViewDelegateFlowLayout> is a subclass of <UICollectionViewDelegate>.
UICollectionViewDataSource Protocol Documentation
UICollectionViewDelegate Protocol Documentation
And the Swift version
Drag a UICollectionView into your UIView and size it appropriately.
Modify your UIViewController to extend UICollectionViewDataSource and UICollectionViewDelegate
Implement the required functions
Control-Drag from your storyboard to the class to create an outlet 'collectionView'
In the viewDidLoad() wire up the delegate and datasource to self
collectionView.delegate = self and collectionView.dataSource = self
It should end up looking like this:
class CustomerViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate
{
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
collectionView.delegate = self
collectionView.dataSource = self
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
}
func collectionView(collectionView: UICollectionView, didEndDisplayingCell cell: UICollectionViewCell, forItemAtIndexPath indexPath: NSIndexPath) {
}
func collectionView(collectionView: UICollectionView, didEndDisplayingSupplementaryView view: UICollectionReusableView, forElementOfKind elementKind: String, atIndexPath indexPath: NSIndexPath) {
}
}
Drag a UICollectionView into your UIView and size it appropriately.
Create a property which is also an IBOutlet in your .h file for the collection view:
#property (nonatomic, retain) IBOutlet UICollectionView *myCollectionView;
in UIView first you need to declare your UICollectionView cell in -(void)awakeFromNib
[myCollectionView registerNib:[UINib nibWithNibName:#"nib file of collectionView cell" bundle:nil] forCellWithReuseIdentifier:#"identifier"];
then
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
custom class *cell1=[collectionView dequeueReusableCellWithReuseIdentifier:#"identifier" forIndexPath:indexPath];
return cell1;
}
Drag uiviewcontroller to the stroryboard.
Create the new class file for the new uiviewcontoller
Set the newly created class to our viewcontroller. And add protocol methods to the .h file. -UICollectionViewDelegate,UICollectionViewDataSource
Drag uicollectionview to the viewcontroller, by default there will be a uicollectionviewcell with the collectionview.
Create new class for the cell customisation as the subclass of the uicollectionviewcell and set the class to the cell in the identity inspector. Also set reuse identifier in the attributes inspector, the name we should specify to identify the uicollectionviewcell. Say cell here.
Drag and drop an imageview(can be anything as your wish) inside the uicollectionviewcell, size it to fit within.
Set an image with the imageview(this image will be shown repeatedly with the collectionview).
Set the delegate and datasource with the uicollectionview to the corresponding viewcontroller.
Set datasource methods - numberOfItemsInSection and cellForItemAtIndexPath.
Return the required cell count with the numberOfItemsInSection method. Say 10 here.
Return the cell to display with the cellForItemAtIndexPath.
NSString * identifier = #"cell";
CollectionViewCellForDay * cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
return cell;
By now, you should be able to have a visual of a 10 cell collection view :)
Related
I am having trouble getting this code to run after having it crash after several iterations. The intended behaviour is to simply display images in a Collection View from an array. If I comment out all the objects in the array, it runs with an empty collection view.
logo.png exists and can be properly loaded in other parts of the app through the dropdown. Delegate and DataSource is properly set to self. The Collection View has a single cell displayed with an ImageView in it (tagged as 100) and nothing else. Having a label instead of an image view causes a crash with any objects in the array as well.
The debugging output is
Could not dequeue a view of kind: UICollectionElementKindCell with identifier Cell - must
register a nib or a class for the identifier or connect a prototype cell in a storyboard
The relevant code is the following:
ViewController.m
#import "demo_frameworkViewController.h"
#interface demo_frameworkViewController ()
#end
#implementation demo_frameworkViewController {
NSMutableArray *imageArray;
}
#synthesize imageArray;
- (void)viewDidLoad
{
imageArray = [[NSMutableArray alloc] init];
[imageArray addObject:[UIImage imageNamed:#"logo.png"]];
[imageArray addObject:[UIImage imageNamed:#"logo.png"]];
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark Collection View Methods
-(NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView {
return 1;
}
-(NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section{
return [self.imageArray count];
}
-(UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
UIImageView *imageDemo = (UIImageView *)[cell viewWithTag:100];
imageDemo.image =[imageArray objectAtIndex:indexPath.row];
[cell.layer setBorderWidth:2.0f];
[cell.layer setBorderColor:[UIColor whiteColor].CGColor];
return cell;
}
#end
ViewController.h
#import <UIKit/UIKit.h>
#interface demo_frameworkViewController : UIViewController <UINavigationControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource>
#property (nonatomic, retain) NSArray *imageArray;
#property (weak, nonatomic) IBOutlet UIImageView *imageView;
#end
The debugging output means that it cannot find a cell called 'Cell'. In your storyboard you need to set the Collection Reusable View value of the UICollectionViewCell to 'Cell' so that the UICollectionView knows what cell to use
I cannot create any IBOutlets. I'm using a tableviewcontroller instead of a viewcontroller.
When I click on TableViewController, the class is UITableViewController and I can't change that.
Here's my code for ViewController.h:
// ViewController.h
// Tips4
//
// Created by Meghan on 1/20/14.
// Copyright (c) 2014 Meghan. All rights reserved.
//
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
#property (strong, nonatomic) IBOutlet UILabel *sliderDisplay;
#property (strong, nonatomic) IBOutlet UITextField *tempText;
#property (strong, nonatomic) IBOutlet UILabel *billTotal;
#property (nonatomic, strong) IBOutlet UISlider *slider;
- (IBAction)sliderValueChanged:(id)sender;
#property (nonatomic) float answer;
#property (nonatomic) float answerTwo;
#end
Here's my ViewController.m:
// ViewController.m
// Tips4
//
// Created by Meghan on 1/20/14.
// Copyright (c) 2014 Meghan. All rights reserved.
//
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 10;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *tipsTableIdentifier = #"TipsTableCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:tipsTableIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:tipsTableIdentifier];
}
return cell;
}
- (IBAction)sliderValueChanged:(id)sender
{
float theText = [_tempText.text floatValue];
_answer = (_slider.value * theText) / 100;
_answerTwo = _answer + theText;
_sliderDisplay.text = [NSString stringWithFormat:#"%1.2f", _answer];
_billTotal.text = [NSString stringWithFormat:#"%1.2f", _answerTwo];
}
- (void)viewDidLoad
{
[super viewDidLoad];
_tempText.keyboardType = UIKeyboardTypeDecimalPad;
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
If you’re using a TableViewController, your class must inherit from a UITableViewController. Thats when it will show up in the Identity Inspector, which is where you change your class from UIViewController to your class. After that you should be able to connect IBOutlets.
To do that, just replace your current line
#interface ViewController : UIViewController <UITableViewDelegate, UITableViewDataSource>
with
#interface ViewController : UITableViewController
Now, you will need to add the init method that calls the super, to the .m file.
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
I hope this will do it.
Also, sometimes, changes in the code don’t show up in the storyboard Identity Inspector. In that case, you can just quit the Xcode window and open the project again. That does it.
Alternatively, if you use a ViewController, your class can inherit from a UIViewController. Then you add a TableView to your View and add a UITableView instance to the controller file (create an IBOutlet). In this case, your .h file needs to add the UITableViewDelegate and UITableViewDataSource to populate the table and your .m file needs to implement the required methods (Xcode will warn you about this).
I'm trying to detect when a mouse click occurs in an NSTableView, and when it does, to determine the row and column of the cell that was clicked.
So far I've tried to use NSTableViewSelectionDidChangeNotification, but there are two problems:
It only triggers when the selection changes, whereas I want every mouse click, even if it is on the currently selected row.
The clickedRow and clickedColumn properties of NSTableView are both -1 when my delegate is called.
Is there a better (and correct) way of doing this?
There is a simple way.
Tested with Swift 3.0.2 on macOS 10.12.2 and Xcode 8.2.1
Let
tableView.action = #selector(onItemClicked)
Then
#objc private func onItemClicked() {
print("row \(tableView.clickedRow), col \(tableView.clickedColumn) clicked")
}
To catch the user clicking a row (only, when the user clicks a row, not when it is selected programmatically) :
Subclass your NSTableView and declare a protocol
MyTableView.h
#protocol ExtendedTableViewDelegate <NSObject>
- (void)tableView:(NSTableView *)tableView didClickedRow:(NSInteger)row;
#end
#interface MyTableView : NSTableView
#property (nonatomic, weak) id<ExtendedTableViewDelegate> extendedDelegate;
#end
MyTableView.m
Handle the mouse down event (note, the delegate callback is not called when the user clicks outside, maybe you want to handle that too, in that case, just comment out the condition "if (clickedRow != -1)")
- (void)mouseDown:(NSEvent *)theEvent {
NSPoint globalLocation = [theEvent locationInWindow];
NSPoint localLocation = [self convertPoint:globalLocation fromView:nil];
NSInteger clickedRow = [self rowAtPoint:localLocation];
[super mouseDown:theEvent];
if (clickedRow != -1) {
[self.extendedDelegate tableView:self didClickedRow:clickedRow];
}
}
Make your WC, VC conform to ExtendedTableViewDelegate.
#interface MyViewController : DocumentBaseViewController<ExtendedTableViewDelegate, NSTableViewDelegate, NSTableViewDataSource>
set the extendedDelegate of the MyTableView to your WC, VC (MyViewController)
somewhere in MyTableView.m
self.myTableView.extendedDelegate = self
Implement the callback in delegate (MyViewController.m)
- (void)tableView:(NSTableView *)tableView didClickedRow:(NSInteger)row {
// have fun
}
I would prefer doing as follows.
Override
-(BOOL)tableView:(NSTableView *)tableView shouldSelectRow:(NSInteger)row;
Provide super implementation;
RequiredRow = row;
RequiredColumn = [tableView clickedColumn];
Hope this helps.
If someone is looking for a Swift 3/4/5 version of Peter Lapisu's answer:
Add an extension for the NSTableView (NSTableView+Clickable.swift):
import Foundation
import Cocoa
extension NSTableView {
open override func mouseDown(with event: NSEvent) {
let globalLocation = event.locationInWindow
let localLocation = self.convert(globalLocation, from: nil)
let clickedRow = self.row(at: localLocation)
super.mouseDown(with: event)
if (clickedRow != -1) {
(self.delegate as? NSTableViewClickableDelegate)?.tableView(self, didClickRow: clickedRow)
}
}
}
protocol NSTableViewClickableDelegate: NSTableViewDelegate {
func tableView(_ tableView: NSTableView, didClickRow row: Int)
}
Then to use it, make sure you implement the new delegate protocol:
extension MyViewController: NSTableViewClickableDelegate {
#nonobjc func tableView(_ tableView: NSTableView, didClickRow row: Int) {
Swift.print("Clicked row \(row)")
}
}
The #nonobjc attribute silences the warning about it being close to didClick.
Just in case someone was looking for it in SWIFT and / or for NSOutlineView.
Based on #Peter Lapisu instructions.
class MYOutlineViewDelegate: NSOutlineView, NSOutlineViewDelegate,NSOutlineViewDataSource{
//....
}
extension MYOutlineViewDelegate{
func outlineView(outlineView: NSOutlineView, didClickTableRow item: AnyObject?) {
//Click stuff
}
override func mouseDown(theEvent: NSEvent) {
let globalLocation:NSPoint = theEvent.locationInWindow
let localLocation:NSPoint = self.convertPoint(globalLocation, fromView: nil)
let clickedRow:Int = self.rowAtPoint(localLocation)
super.mouseDown(theEvent)
if (clickedRow != -1) {
self.outlineView(self, didClickTableRow: self.itemAtRow(clickedRow))
}
}}
see the tableViewSelectionIsChanging notification, here are the the comments from NSTableView.h
/*
Optional - Called when the selection is about to be changed, but note, tableViewSelectionIsChanging: is only called when mouse events are changing the selection and not keyboard events.
*/
I concede that this might not be the surest way to correlate your mouse clicks, but it is another area to investigate, seeing that you are interested in mouse clicks.
NSCollectionView remains one of the most mysterious parts of the Cocoa API that I've ever seen. Documentation is poor and there are many moving parts, many of which are often implemented in Interface Builder, making documentation challenging.
Please provide sample code to create the simplest case of NSCollectionView which displays either Text Fields or Buttons without using Xcode where each Text Field or Button has a different Title. Assume a new Xcode project with the default window IBOutlet.
For this example, no binding is required to update the NSCollectionView as the data source changes. Simply display a grid of prototype objects and set each object's Title to some value.
If we can get a good example of how to do this available to many people, I think it will help everyone who works with NSCollectionViews and is as baffled as I am.
Summary of request
Provide sample code to render an NSCollectionView in a new Xcode project
Do not use Interface Builder, do use the default window IBOutlet provided
NSCollectionView should contain Text Fields or Buttons, your choice
Each item in the view should have a different Title
No binding is required
If there's sample code out there that meets these requirements, please provide a link, that'd be great!
I’m not sure there’s much insight in creating a collection view programmatically and without bindings, but here it goes.
Introduction
There are essentially four components when using a collection view:
View: a subclass of NSView, responsible for displaying information;
The collection view itself;
View controller: a subclass of NSCollectionViewItem that serves as the collection view item prototype;
Model: an array of objects.
Usually a view is designed in Interface Builder, and a model is mediated by Cocoa bindings.
Doing it programmatically:
Constants
static const NSSize buttonSize = {80, 20};
static const NSSize itemSize = {100, 40};
static const NSPoint buttonOrigin = {10, 10};
View
This is a standard view (a custom view in Interface Builder parlance) containing a button. Note that the view has fixed size.
#interface BVView : NSView
#property (weak) NSButton *button;
#end
#implementation BVView
#synthesize button;
- (id)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:(NSRect){frameRect.origin, itemSize}];
if (self) {
NSButton *newButton = [[NSButton alloc]
initWithFrame:(NSRect){buttonOrigin, buttonSize}];
[self addSubview:newButton];
self.button = newButton;
}
return self;
}
#end
View Controller (Prototype)
Normally a view controller loads its view from a nib file. In the rare cases where the view controller doesn’t obtain its view from a nib file, the developer must either send it -setView: before -view is received by the view controller, or override -loadView. The following code does the latter.
View controllers receive the corresponding model object via -setRepresentedObject:. I’ve overridden it so as to update the button title whenever the model object changes. Note that this can be accomplished by using Cocoa bindings without any code at all.
Note that none of this code is specific to collection views — it’s general view controller behaviour.
#interface BVPrototype : NSCollectionViewItem
#end
#implementation BVPrototype
- (void)loadView {
[self setView:[[BVView alloc] initWithFrame:NSZeroRect]];
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
[[(BVView *)[self view] button] setTitle:representedObject];
}
#end
Model
A simple array of strings representing button titles:
#property (strong) NSArray *titles;
self.titles = [NSArray arrayWithObjects:#"Case", #"Molly", #"Armitage",
#"Hideo", #"The Finn", #"Maelcum", #"Wintermute", #"Neuromancer", nil];
Collection View
So far, the only relation that’s been established is the view (BVView) used by the item prototype (BVPrototype). The collection view must be informed of the prototype it should be using as well as the model from which to obtain data.
NSCollectionView *cv = [[NSCollectionView alloc]
initWithFrame:[[[self window] contentView] frame]];
[cv setItemPrototype:[BVPrototype new]];
[cv setContent:[self titles]];
Full Source Code for the Application Delegate
#import "BVAppDelegate.h"
static const NSSize buttonSize = { 80, 20 };
static const NSSize itemSize = { 100, 40 };
static const NSPoint buttonOrigin = { 10, 10 };
#interface BVView : NSView
#property (weak) NSButton *button;
#end
#implementation BVView
#synthesize button;
- (id)initWithFrame:(NSRect)frameRect {
self = [super initWithFrame:(NSRect){frameRect.origin, itemSize}];
if (self) {
NSButton *newButton = [[NSButton alloc]
initWithFrame:(NSRect){buttonOrigin, buttonSize}];
[self addSubview:newButton];
self.button = newButton;
}
return self;
}
#end
#interface BVPrototype : NSCollectionViewItem
#end
#implementation BVPrototype
- (void)loadView {
[self setView:[[BVView alloc] initWithFrame:NSZeroRect]];
}
- (void)setRepresentedObject:(id)representedObject {
[super setRepresentedObject:representedObject];
[[(BVView *)[self view] button] setTitle:representedObject];
}
#end
#interface BVAppDelegate ()
#property (strong) NSArray *titles;
#end
#implementation BVAppDelegate
#synthesize window = _window;
#synthesize titles;
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification {
self.titles = [NSArray arrayWithObjects:#"Case", #"Molly", #"Armitage",
#"Hideo", #"The Finn", #"Maelcum", #"Wintermute", #"Neuromancer", nil];
NSCollectionView *cv = [[NSCollectionView alloc]
initWithFrame:[[[self window] contentView] frame]];
[cv setItemPrototype:[BVPrototype new]];
[cv setContent:[self titles]];
[cv setAutoresizingMask:(NSViewMinXMargin
| NSViewWidthSizable
| NSViewMaxXMargin
| NSViewMinYMargin
| NSViewHeightSizable
| NSViewMaxYMargin)];
[[[self window] contentView] addSubview:cv];
}
#end
#Bavarious
You did an excellent job there. This was just an amazing tutorial which I sometimes miss at the Apple Docs.
I rewrote Bavarious' code in Swift (v2) for anyone who's interested:
// AppDelegate.swift:
import Cocoa
let buttonSize:NSSize = NSSize(width: 80, height: 20)
let itemSize:NSSize = NSSize(width: 100, height: 40)
let buttonOrigin:NSPoint = NSPoint(x: 10, y: 10)
let titles:[String] = ["Case", "Molly", "Armitage", "Hideo", "The Finn", "Maelcum", "Wintermute", "Neuromancer"]
#NSApplicationMain
class AppDelegate: NSObject, NSApplicationDelegate {
#IBOutlet weak var window: NSWindow!
func applicationDidFinishLaunching(aNotification: NSNotification) {
let cv = NSCollectionView(frame: self.window.contentView!.frame)
cv.itemPrototype = BVTemplate()
cv.content = titles
cv.autoresizingMask = NSAutoresizingMaskOptions.ViewMinXMargin
.union(NSAutoresizingMaskOptions.ViewWidthSizable)
.union(NSAutoresizingMaskOptions.ViewMaxXMargin)
.union(NSAutoresizingMaskOptions.ViewMinYMargin)
.union(NSAutoresizingMaskOptions.ViewMaxYMargin)
.union(NSAutoresizingMaskOptions.ViewHeightSizable)
window.contentView!.addSubview(cv)
}
func applicationWillTerminate(aNotification: NSNotification) {
// Insert code here to tear down your application
}
}
// BVTemplate.swift:
import Cocoa
class BVTemplate: NSCollectionViewItem {
override func viewDidLoad() {
super.viewDidLoad()
// Do view setup here.
}
override func loadView() {
print("loadingView")
self.view = BVView(frame: NSZeroRect)
}
override var representedObject:AnyObject? {
didSet {
if let representedString = representedObject as? String {
(self.view as! BVView).button?.title = representedString
}
}
}
}
// BVView.swift:
import Cocoa
class BVView: NSView {
var button:NSButton?
override init(frame frameRect: NSRect) {
super.init(frame: NSRect(origin: frameRect.origin, size: itemSize))
let newButton:NSButton = NSButton(frame: NSRect(origin: buttonOrigin, size: buttonSize))
self.addSubview(newButton)
self.button = newButton
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
}
To answer brigadir's question on how to bind to a mutable array.
zero'th - make titles an NSMutableArray
first - bind the array to your items
[cv bind:NSContentBinding
toObject:self
withKeyPath:#"titles"
options:NULL];
Second - when altering titles, make sure to modify the proxy.
e.g.
NSMutableArray *kvcTitles = [self mutableArrayValueForKey:#"titles"];
[kvcTitles removeLastObject];
I have Table view Controller and separate class which handles for me tableviewcell. Inside the tableview cell I have pickerview.
How to implement delegate and datasource for pickerview which is in tableCell class but my delegate functions in tableview controller?
For Swift:
Create outlet for UIPickerView in custom table view class:
class MyTableViewCell: UITableViewCell, UIPickerViewDelegate, UIPickerViewDataSource {
#IBOutlet var myPickerView: UIPickerView!
}
Add delegate and datasource in "cellForRowAtIndexPath" in ViewController:
class myViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, UITableViewDelegate, UITableViewDataSource {
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("myCell") as! MyTableViewCell
cell.myPickerView.dataSource = self
cell.myPickerView.delegate = self
return cell
}
}
You could have your tableView controller set a property on the tableview cells as they are created indicating that it is the delegate and datasource.
On the tableviewcell class you created just add a property that is an instance of you tableview controller. Like
#property (nonatomic, retain) MyTableViewController * pickerDelegate;
Then in your cellForRowAtIndexPath you can set that property to self
cell.pickerDelegate = self;
You might need to also set some sort extra property like a tag to distinguish between each cell. I would think another property on the tableviewcell like an NSIndexPath would do.