我正在编写一个应用程序,有人在应用程序中添加联系人,提供他们的姓名,号码和照片。然后,该信息显示在表格中,每个单独的联系人在不同的单元格上,当用户按下该单元格时,它将调用为该联系人输入的号码。我在每个单元格上放了一个大按钮供用户按下。这是代码
PictureListMainTable.m
#import "PictureListMainTable.h"
#import "PictureListDetail.h"
#import "CoreDataHelper.h"
#import "Pictures.h"
@implementation PictureListMainTable
@synthesize managedObjectContext, pictureListData, callButton;
// When the view reappears, read new data for table
- (void)viewWillAppear:(BOOL)animated
{
// Repopulate the array with new table data
[self readDataForTable];
}
// Grab data for table - this will be used whenever the list appears or reappears after an add/edit
- (void)readDataForTable
{
// Grab the data
pictureListData = [CoreDataHelper getObjectsForEntity:@"Pictures" withSortKey:@"title" andSortAscending:YES andContext:managedObjectContext];
// Force table refresh
[self.tableView reloadData];
}
#pragma mark - Actions
// Button to log out of app (dismiss the modal view!)
- (IBAction)logoutButtonPressed:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
}
#pragma mark - Segue methods
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get a reference to our detail view
PictureListDetail *pld = (PictureListDetail *)[segue destinationViewController];
// Pass the managed object context to the destination view controller
pld.managedObjectContext = managedObjectContext;
// If we are editing a picture we need to pass some stuff, so check the segue title first
if ([[segue identifier] isEqualToString:@"EditPicture"])
{
// Get the row we selected to view
NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];
// Pass the picture object from the table that we want to view
pld.currentPicture = [pictureListData objectAtIndex:selectedIndex];
}
}
#pragma mark - Table view data source
// Return the number of sections in the table
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
// Return the number of rows in the section (the amount of items in our array)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [pictureListData count];
}
// Create / reuse a table cell and configure it for display
- (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];
}
// Get the core data object we need to use to populate this table cell
Pictures *currentCell = [pictureListData objectAtIndex:indexPath.row];
// Fill in the cell contents
cell.textLabel.text = [currentCell title];
cell.detailTextLabel.text = [currentCell desc];
int number;
number = [currentCell desc];
-(IBAction)MakePhoneCall:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel:",number]];
}
// If a picture exists then use it
if ([currentCell smallPicture])
{
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
cell.imageView.image = [UIImage imageWithData:[currentCell smallPicture]];
}
else{
}
return cell;
}
// Swipe to delete has been used. Remove the table item
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Get a reference to the table item in our data array
Pictures *itemToDelete = [self.pictureListData objectAtIndex:indexPath.row];
// Delete the item in Core Data
[self.managedObjectContext deleteObject:itemToDelete];
// Remove the item from our array
[pictureListData removeObjectAtIndex:indexPath.row];
// Commit the deletion in core data
NSError *error;
if (![self.managedObjectContext save:&error])
NSLog(@"Failed to delete picture item with error: %@", [error domain]);
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
-(IBAction)MakePhoneCall:(id)sender {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel:",number]];
}
@end
PictureListMainTable.h
#import <UIKit/UIKit.h>
@interface PictureListMainTable : UITableViewController
@property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (strong, nonatomic) NSMutableArray *pictureListData;
@property (nonatomic, retain) IBOutlet UIButton *callButton;
-(IBAction)MakePhoneCall:(id)sender;
- (void)readDataForTable;
@end
我应该在哪里放置IBaction,为什么它在它出现的那一刻起作用?如何才能使它发挥作用?
答案 0 :(得分:1)
您可以采取几种方法来实现这一目标。但首先,我不明白你在-tableview:cellForRowAtIndexPath:
的底部做了什么。就像你试图在这个方法中定义你的IBAction方法一样。您也可以在实现的底部定义它,但在该方法中,number
变量不在范围内。
无论如何,你应该继承UITableViewCell
。在子类的实现中,您应该定义IBAction方法并将其挂钩在接口构建器中,否则。
当点击按钮时,您应该将所选单元格的编号交回PictureListMainTable视图控制器,以便该视图控制器处理它(即调用该编号)。您可以通过两种方式执行此操作:
1)委托方法
创建一个协议,在UITableViewCell子类的头文件中定义。并使主视图控制器符合此协议。将单元格的委托设置为主视图控制器。在单元子类的实现中,调用此委托方法。例如:
UITableViewCell子类“PictureListMainTableCell.h”的头文件
@protocol PictureListMainTableCellDelegate;
@interface PictureListMainTableCell : UITableViewCell
@property (nonatomic, copy) NSString *telephoneNumber;
@property (nonatomic, weak) id<PictureListMainTableCellDelegate> delegate;
@end
@protocol PictureListMainTableCellDelegate
-(void)pictureListMainTableCell:(PictureListMainTableCell *)cell wantsToCallNumber:(NSString *)number;
@end
实施文件“PictureListMainTableCell.m”
#import "PictureListMainTableCell.h"
@implementation PictureListMainTableCell
-(IBAction)MakePhoneCall:(id)sender
{
//send the delegate the number to call.
[self.delegate pictureListMainTableCell:self wantsToCallNumber:self.telephoneNumber];
}
@end
上面,在MakePhoneCall方法中,我们在委托上调用-pictureListMainTableCell:wantsToCallNumber:
。在这种情况下,委托是您的主视图控制器。我们将在下面进行设置。
设置单元格的委托:在主视图控制器文件(PictureListMainTable.m)中,在-tableView:cellForRowAtIndexPath:
方法中,将单元格上的委托设置为self
。 e.g。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// get the cell...
PictureListMainTableCell *cell = // dequeue the cell
// do some other setting up...
// set the delegate on the cell
cell.delegate = self;
// set the telephoneNumber variable on the cell, for example...
cell.telephoneNumber = [currentCell desc];
return cell;
}
现在您需要确保self
实现委托方法。所以仍然在PictureListMainTable.m中,您需要按如下方式定义方法:
#pragma mark - PictureListMainTableCellDelegate methods
-(void)pictureListMainTableCell:(PictureListMainTableCell *)cell wantsToCallNumber:(NSString *)number
{
NSString *urlString = [NSString stringWithFormat:@"tel://%@", number];
NSLog(@"calling telephone number [%@]", number);
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:urlString]];
}
您还应该指定PictureListMainTable类符合您的新协议以及UITableViewDataSource协议。在PictureListMainTable上添加一个私有类别,如下所示(在执行文件的顶部,在导入之后,在@implementation
之前):
@interface PictureListMainTable () <UITableViewDataSource, PictureListMainTableCellDelegate>
@end
(这扩展了PictureListMainTable接口。它只扩展它以私下指定它符合这些协议。)
2)NSNotification方法
当我输入上述解释时,我认为这是我首选的做事方式,所以我建议这样做。可以选择在您的单元子类中发布NSNotification,并从主视图控制器观察此通知。只需查看NSNotificationCenter,可以使用以下方法:
–postNotificationName:object:userInfo:
(在userInfo字典中发送号码)。使用–addObserver:selector:name:object:
收听它。
但就像我说的那样,在我看来,选项1更好。
如果有什么不清楚,请告诉我,祝你好运:)。
编辑:我真的建议您阅读此博文以了解授权:http://alexefish.com/post/15966868557/understanding-and-creating-delegates-in-objective-c