I have 3 custom table cells in my UITableView. The first two cells have set positions followed by a random number of cells.
For my row count I use :
return [stepLabel count] +2;
And for my tablecells I use :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *stepsCellIdentifier = #"StepsViewCell";
static NSString *descIdentfier = #"descViewCell";
static NSString *videoCellIdentfier = #"videoViewCell";
if( indexPath.row == 0 ) {
UITableViewCell *cell = nil;
cell = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:videoCellIdentfier];
if( !cell ) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"videoViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.textLabel.text = [descLabel objectAtIndex:indexPath.row];
return cell;
}
else if( indexPath.row == 1 ) {
stepDescCell *cell = nil;
cell = (stepDescCell *)[tableView dequeueReusableCellWithIdentifier:descIdentfier];
if( !cell ) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"descViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.descTextLabel.text = [descLabel objectAtIndex:indexPath.row - 1];
return cell;
}
else {
StepViewCell *cell = nil;
cell = (StepViewCell *)[tableView dequeueReusableCellWithIdentifier:stepsCellIdentifier];
if( !cell ) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"StepsViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.stepTextLbl.text = [stepLabel objectAtIndex:(indexPath.row - 2)];
NSString *imageThumb = [thumbImg objectAtIndex:(indexPath.row - 2)];
[cell.thumbImage setImage:[UIImage imageNamed: imageThumb] forState:UIControlStateNormal];
return cell;
}
}
All this works perfectly, however when I try to send a string from the table across a segue to another UIViewController I get the following error:
index (-2 (or possibly larger)) beyond bounds (3)'
The prepare for segue method:
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
if ([segue.identifier isEqualToString:#"imageBigShow"]) {
NSIndexPath *indexPath = [self.tableView indexPathForSelectedRow];
imageBigViewController *destViewController = segue.destinationViewController;
NSString *largeImgString = [largeImg objectAtIndex:(indexPath.row - 2)];
destViewController.imageBigString = largeImgString;
}
}
What am I doing wrong?
UPDATE
#implementation detailViewController
{
NSArray *thumbImg;
NSArray *stepLabel;
NSArray *descLabel;
NSArray *largeImg;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Find out the path of recipes.plist
NSDictionary *mapping = #{
#"How to wear a Kilt" : #"wearAKilt",
#"How to tie a cravat" : #"wearACravat",
#"How to wear a sporran" : #"wearASporran",
#"How to tie Ghillie Brogues" : #"wearTheShoes",
#"How to wear the accessories" : #"wearAccessories",
#"How to tie a cravat" : #"wearACravat",
#"How to Measure the Neck" : #"htmNeck",
#"How to Measure the chest" : #"htmChest",
#"How to Measure the waist" : #"htmWaist",
};
NSString *name = [mapping objectForKey:self.title];
NSString *path = [[NSBundle mainBundle] pathForResource:name ofType:#"plist"];
// Load the file content and read the data into arrays
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
thumbImg = [dict objectForKey:#"thumbImg"];
stepLabel = [dict objectForKey:#"stepLabel"];
descLabel = [dict objectForKey:#"descLabel"];
largeImg = [dict objectForKey:#"largeImg"];
}
You have the following line:
NSString *largeImgString = [largeImg objectAtIndex:(indexPath.row - 2)];
If the user taps on the 1st or 2nd rows (index paths with row 0 or 1), this code will fail.
Related
I am using the following code to have a tab view. When you click one tab it expands downwards, this is currently working okay but if I open the first tab with the indexPath of 0 which should load a separate custom opened view it will load but then when I go to the other indexPath tabs it displays the same view but if I reload the app and go to the other tabs first they load the correct view. It's nearly like the app is making a cache?
Is there any way to solve this??
Thanks
- (void)viewDidLoad {
row = 1000;
NSLog(#"row is %d", row);
[super viewDidLoad];
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
infoStory = [userDefaults objectForKey:#"storyname"];
// Do any additional setup after loading the view.
numbers = [NSArray arrayWithObjects:#"1", #"2", #"3", #"4", #"5", #"6", #"7", #"8", nil];
// Initialize thumbnails
text = [NSArray arrayWithObjects: #"Arriving by Bus or Train", #"Arriving by Car (Autobahn 5)", #"Arriving by Car (Autobahn 6)", #"Wifi", #"Registration", #"Refreshments", #"Evening Event", #"Contact Information", nil];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if(row == indexPath.row){
if(indexPath.row == 0){
static NSString *simpleTableIdentifier2 = #"TableViewCellOPENEDbustaxi2";
TableViewCell1 *cell = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier2];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellOPENEDbustaxi2" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.text.text = [text objectAtIndex:indexPath.row];
return cell;
}
else{
static NSString *simpleTableIdentifier = #"TableViewCellOPENED";
TableViewCell1 *cell2 = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell2 == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellOPENED" owner:self options:nil];
cell2 = [nib objectAtIndex:0];
}
cell2.text.text = [text objectAtIndex:indexPath.row];
return cell2;
}
}
else{
static NSString *simpleTableIdentifier = #"TableViewCellINFO";
TableViewCell1 *cell = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellINFO" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
cell.text.text = [text objectAtIndex:indexPath.row];
return cell;
}
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [numbers count];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if(row == indexPath.row){
row = 1000;
NSLog(#"row is %d", row);
[self.tableViewObject reloadData];
}
else{
row = indexPath.row;
NSLog(#"row is %d", row);
[self.tableViewObject reloadData];
}
}
#end
I think the problem might be that you did not specify the correct reuse identifier in the attributes inspector of the cell in your XIB file(s). You should check if you use the wrong one somewhere, so dequeueing will return an unexpected cell.
You could also set the appropriate reuseIdentifier manually, with a little setValue:forKey: trick:
static NSString *simpleTableIdentifier2 = #"TableViewCellOPENEDbustaxi2";
TableViewCell1 *cell = (TableViewCell1 *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier2];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"TableViewCellOPENEDbustaxi2" owner:self options:nil];
cell = [nib objectAtIndex:0];
[cell setValue:simpleTableIdentifier2 forKey:#"reuseIdentifier"];
}
and so on for the other cells and identifiers.
I'm using one type of Custom Table View Cell, but when other data is posted to my Table View, I want it to be displayed in a different Custom Table View Cell in the same table.
For example, I've created a chat in my Table View. However when certain details are posted, I want a separate cell design to display these details. See my code below so far.
My question: How can I write, "If field_swaptime in self.messages is empty, display ChatTableViewCell - if it contains data, display SwapDetailTableViewCell" ?
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *ChatTableIdentifier = #"ChatTableViewCell";
static NSString *ChatTableIdentifier2 = #"SwapDetailTableViewCell";
NSDictionary *data = [self.messages objectAtIndex:indexPath.row];
if ( [data objectForKey:#"field_swaptime"] == nil ) {
NSLog(#"THIS IS DATA %#", data);
ChatTableViewCell *cell = (ChatTableViewCell *)[tableView dequeueReusableCellWithIdentifier:ChatTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ChatTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSString *userName = [data objectForKey:#"name"];
[cell.sendingUser setText:userName];
NSString *messageBody = [data objectForKey:#"body"];
[cell.messageDisplayed setText:messageBody];
NSString *timeReceived = [data objectForKey:#"published at"];
NSLog(#"Message Received at %#", timeReceived);
[cell.timeStamp setText:timeReceived];
return cell;
}
else {
SwapDetailTableViewCell *cell = (SwapDetailTableViewCell *)[tableView dequeueReusableCellWithIdentifier:ChatTableIdentifier2];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SwapDetailTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSString *Time = [data objectForKey:#"field_swaptime"];
NSLog(#"This is time %#", Time);
[cell.startTime setText:Time];
NSString *TimeEnd = [data objectForKey:#"field_endswaptime"];
[cell.endTime setText:TimeEnd];
return cell;
}
}
You are basically looking to write your initial if as:
NSDictionary *data = [self.messages objectAtIndex:indexPath.row];
//
// if self.messages is nil, then data will be nil and we'll display
// a ChatTableViewCell as before. If data is valid, but there is no
// value associated with "field_swaptime", then again, we'll display
// a ChatTableViewCell. However, if self.messages IS valid and
// there IS a value associated with "field_swaptime" key, then the
// if clause fails, and we execute the else and return a
// SwapDetailTableViewCell.
//
if ( !data || ![data objectForKey:#"field_swaptime"] } {
ChatTableViewCell *cell = (ChatTableViewCell *)[tableView dequeueReusableCellWithIdentifier:ChatTableIdentifier];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ChatTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSString *userName = [data objectForKey:#"name"];
[cell.sendingUser setText:userName];
NSString *messageBody = [data objectForKey:#"body"];
[cell.messageDisplayed setText:messageBody];
NSString *timeReceived = [data objectForKey:#"published at"];
NSLog(#"Message Received at %#", timeReceived);
[cell.timeStamp setText:timeReceived];
return cell;
}
else {
SwapDetailTableViewCell *cell = (SwapDetailTableViewCell *)[tableView dequeueReusableCellWithIdentifier:ChatTableIdentifier2];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"SwapDetailTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
NSString *Time = [data objectForKey:#"field_swaptime"];
[cell.startTime setText:Time];
NSString *TimeEnd = [data objectForKey:#"field_endswaptime"];
[cell.endTime setText:TimeEnd];
return cell;
}
Bonus: if self.messages is valid, and data is valid, then you already have data and don't need to multiple calls to [self.messages objectAtIndex:indexPath.row]. (you should do a bounds sanity check on self.messages.count against indexPath.row before calling objectAtIndex:indexPath.row, but the defensive coding part is up to you to put together)
Objective C is pretty nifty in that calling a method on nil object, just returns nil. So, it is perfectly valid to ignore whether self.messages is valid or not, and just retrieve the data it contains. If it is valid (and your index is in bounds of the array), then a valid NSDictionary will be returned that you can use throughout the if/else clause.
The type of cell you get is determined by the type you register to correspond with the identifier. So, when you're setting up the table (say, in viewDidLoad)...
UINib *nib = [UINib nibWithNibName:#"ChatTableViewCell" bundle:nil]; // bundle:nil means main bundle
[self.tableView registerNib:nib forCellReuseIdentifier:#"ChatTableIdentifier"];
UINib *nib2 = [UINib nibWithNibName:#"OtherTableViewCell" bundle:nil];
[self.tableView registerNib:nib2 forCellReuseIdentifier:#"OtherIdentifier"];
Then, in cellForRowAtIndexPath, you use the modern dequeue method, dequeueReusableCellWithIdentifier:forIndexPath:, which never returns nil and always returns an instance built from the nib you registered earlier...
// generically
NSString *identifier = (/*some condition*/)? #"ChatTableIdentifier" : #"OtherIdentifier";
// or alternatively, given the condition in your comment...
NSString *identifier = (!data[#"field_swaptime"])? #"ChatTableIdentifier" : #"OtherIdentifier";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:identifier forIndexPath:indexPath];
// now cell is one of your two custom classes, built from their respective nibs.
Based on the same condition, you can cast cell to either kind, and configure it...
if (/*same condition as identifier*/) {
ChatTableViewCell *chatCell = (ChatTableViewCell *)cell;
// do your config for this type here
} else {
OtherTableViewCell *otherTypeCell = (OtherTableViewCell *)cell;
// do your config for this other type here
}
return cell;
I'm binding json datas. Json send me km (kilometer) format float . like ; km=850.564636
I want put in cell this km data. like 850.56
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *simpleTableIdentifier = #"KmCellTableViewCell";
KmCellTableViewCell *cell = (KmCellTableViewCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier];
if (cell == nil)
{
NSString *system = [[UIDevice currentDevice] model];
if ([system isEqualToString:#"iPhone Simulator"]) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"KmCellTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}else
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"KmCellTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
}
Vehicle *GetVehicle = (Vehicle *)[ResultVehicles objectAtIndex:indexPath.row];
cell.txtPlate.text = [GetVehicle Plate];
cell.txtKm.text = [NSString stringWithFormat:#"%# km",[GetVehicle km]]; return cell; }
i formatted another class. but not in cell.i have to formatted in cell. like this in -(void)FirstBinding{} method
Vehicle *GetVehicle = (Vehicle *)[ResultVehicles objectAtIndex:indexPath.row];
cell.txtPlate.text = [GetVehicle Plate];
cell.txtKm.text = [NSString stringWithFormat:#"%# km",[GetVehicle km]]; return cell;}double km = [[vehiclesList objectForKey:#"total_km"] doubleValue];
NSNumberFormatter* nf = [[NSNumberFormatter alloc] init];
nf.positiveFormat = #"#,##0.00";
NSString* s = [nf stringFromNumber: [NSNumber numberWithFloat: km]];
txtKilometer.text = [NSString stringWithFormat:#"%#",s];
I have a UITableView that holds an FBProfilePictureView and a UILable,
my problem is when a user scrolls the picture rebuilds its self and it takes time to show the image it self, i want to know how can i create the FBProfilePictureView once and then when the user scrolls it won't build it self again.
Here is my code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
Messages *msg = [messages objectAtIndex:indexPath.row];
NSUserDefaults *def = [NSUserDefaults standardUserDefaults];
NSData *encodedDataObject = [def objectForKey:#"myUser"];
User *user = (User *)[NSKeyedUnarchiver unarchiveObjectWithData: encodedDataObject];
if(![msg.wrote_id isEqualToString:user.fid])
{
NSString *idToImage = [self getOtherUserId];
NSString *CellIdentifier = #"Cell";
ChatWindowCell *cell = nil;
cell = (ChatWindowCell *)[tableChat dequeueReusableCellWithIdentifier:CellIdentifier];
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ChatWindowCell" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[ChatWindowCell class]])
{
cell = (ChatWindowCell *) currentObject;
cell.profile_image.profileID=nil;
if(cell.profile_image.profileID.length>0)
{
return cell;
}
break;
}
}
cell.profile_image.profileID = idToImage;
NSString *text = msg.msg;
cell.lblMessage.text=text;
return cell;
}
else
{
NSString *CellIdentifier = #"Cell";
ChatCellMe *cell = nil;
cell = (ChatCellMe *)[tableChat dequeueReusableCellWithIdentifier:CellIdentifier];
// if (cell == nil) {
NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:#"ChatCellMe" owner:nil options:nil];
for(id currentObject in topLevelObjects)
{
if([currentObject isKindOfClass:[ChatCellMe class]])
{
cell = (ChatCellMe *) currentObject;
NSLog(cell.prof_img.profileID);
cell.prof_img.profileID=nil;
if(cell.prof_img.profileID.length>0)
{
return cell;
}
break;
}
}
cell.prof_img.profileID = user.fid;
NSString *text = msg.msg;
cell.lblText.text=text;
isMessageFromMe=false;
return cell;
}
}
any help would be great guys...
thanks a lot.
I created an alternate view to solve this problem, see https://github.com/combinatorial/DBFBProfilePictureView
I am new at IOS programing and I have program that works fine, but I found out that it has memory leek, so I start releasing object.
When I now start the program it give me an error:
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
and :
Thread 1: EXC_BAD_ACCESS (code = 1, address = 0x3f800010)
I tried to debug it and I found out that program crashed at creating tableView.
It create whole first section, but in the second row in second section it crashed in the returning line.
here is my code of creating table:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
[tableView setBackgroundView:nil];
tableView.backgroundColor = [UIColor clearColor];
// Configure the cell...
if ([self tableView:tableView canCollapseSection:indexPath.section])
{
if (!indexPath.row)
{
static NSString *CellIdentifier = #"TitleCell";
UILabel *title;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = nil;
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"TitleCell" owner:self options:nil];
titleCell.layer.masksToBounds = YES;
titleCell.layer.cornerRadius =0.0;
cell = titleCell;
self.titleCell = nil;
}
title =(UILabel *)[cell viewWithTag:1];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
NSString *orderString=[[[NSString alloc] init] autorelease];
title.text = [[titles objectAtIndex:indexPath.section] objectAtIndex:2];
cell.accessoryView = nil;
if (!isPad()) {
[cell.contentView setBackgroundColor:[UIColor colorWithRed:0.0 green:0.18 blue:0.24 alpha:1]];
}
return cell;
}
else
{
// all other rows
static NSString *CellIdentifier = #"DataCell";
UILabel *title;
UILabel *update;
UILabel *download;
UILabel *updateText;
UILabel *downloadText;
UIImageView *favoriteIcon;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = nil;
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"DataCell" owner:self options:nil];
cell = dataCell;
self.dataCell = nil;
}
cell.layer.cornerRadius =0;
title =(UILabel *)[cell viewWithTag:1];
download = (UILabel *)[cell viewWithTag:3];
update = (UILabel *)[cell viewWithTag:2];
favoriteIcon = (UIImageView *)[cell viewWithTag:4];
updateText = (UILabel *)[cell viewWithTag:5];
downloadText = (UILabel *)[cell viewWithTag:6];
updateText.text = NSLocalizedString(#"updated", nil);
downloadText.text = NSLocalizedString(#"downloaded", nil);
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"MM. d. YYYY"];
starIcone = favoriteIcon;
int indicator = 0;
for (int i=0; i<[allData count]; i++) {
if ([[[allData objectAtIndex:i] objectAtIndex:1] isEqualToNumber:[[titles objectAtIndex:indexPath.section] objectAtIndex:0]] ) {
indicator++;
}
if (indicator == indexPath.row) {
title.text = [[allData objectAtIndex:i] objectAtIndex:2];
download.text = [dateFormat stringFromDate:[self db_get_date:[[[allData objectAtIndex:i] objectAtIndex:0]intValue]]];
update.text = [dateFormat stringFromDate:[[allData objectAtIndex:i] objectAtIndex:3]];
break;
}
}
[dateFormat release];
[favoriteIcon setAccessibilityHint:title.text];
if ([favorits count]==0) {
favoriteIcon.image = [[UIImage alloc]
initWithContentsOfFile:
[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:
#"blankstar.png"]];
}
for (int i=0; i<[favorits count]; i++) {
if ([title.text isEqualToString:[[favorits objectAtIndex:i] objectAtIndex:2]]) {
favoriteIcon.image = [[UIImage alloc]
initWithContentsOfFile:
[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:
#"star.png"]];
break;
}
else {
favoriteIcon.image = [[UIImage alloc]
initWithContentsOfFile:
[[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:
#"blankstar.png"]];
}
}
UITapGestureRecognizer *recognizer = [[[UITapGestureRecognizer alloc]
initWithTarget:self action:#selector(AddIcone:)]autorelease
];
[favoriteIcon setUserInteractionEnabled:YES];
[favoriteIcon addGestureRecognizer:recognizer];
cell.backgroundColor = [UIColor clearColor];
cell.selectionStyle = UITableViewCellSelectionStyleBlue;
return cell;
}
}
return nil;
I also tried just putting :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"TitleCell";
UILabel *title;
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = nil;
if (cell == nil) {
self.titleCell = [[[NSBundle mainBundle] loadNibNamed:#"TitleCell" owner:self options:nil]objectAtIndex:0];
titleCell.layer.masksToBounds = YES;
titleCell.layer.cornerRadius =0.0;
cell = titleCell;
self.titleCell = nil;
}
return cell;
and it crash as before.
pleas help me out and thank for your help.
[[NSBundle mainBundle] loadNibName: owner: options:] returns an array.
Replace this line with:
self.titleCell = [[[NSBundle mainBundle] loadNibNamed:#"TitleCell" owner:self options:nil] objectAtIndex:0];