1

誰かが連絡先をアプリに追加して、名前、番号、写真を提供するアプリを書いています。次に、この情報がテーブルに表示され、個々の連絡先が異なるセルに表示されます。ユーザーがセルを押すと、連絡先に入力された番号に電話がかかります。ユーザーが押すために、各セルに大きなボタンを配置しました。これがコードです

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 をどこに配置する必要がありますか? また、IBaction が動作しているのになぜ動作しないのですか? どうすれば動作させることができますか?

4

1 に答える 1

1

これを実現するには、いくつかの方法があります。しかし、まず、あなたが の一番下で何をしているのかわかりません-tableview:cellForRowAtIndexPath:。このメソッド内で IBAction メソッドを定義しようとしているかのようです。実装の下部にも定義されていますが、そのメソッドではnumber変数はスコープ内にありません。

とにかく、サブクラス化する必要がありますUITableViewCell。サブクラスの実装では、IBAction メソッドを定義し、それをインターフェイス ビルダーなどに接続する必要があります。

ボタンがタップされたら、選択したセルの番号を PictureListMainTable ビュー コントローラに戻して、そのビュー コントローラがそれを処理できるようにする (つまり、番号を呼び出す) 必要があります。これは、次の 2 つの方法で行うことができます。

1) デリゲート メソッド

UITableViewCell のサブクラスのヘッダー ファイルで定義されたプロトコルを作成します。そして、メインのView Controllerをこのプロトコルに準拠させます。セルのデリゲートをメイン ビュー コントローラーに設定します。cell サブクラスの実装で、このデリゲート メソッドを呼び出します。例えば:

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ます。例えば

- (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

于 2013-08-06T20:51:35.713 に答える