0

私は Objective-C を初めて使用し、委譲の概念をまだ明確に把握していない可能性がありますが、それを使用してそれを実現したいと考えています。アプリに委任を実装しようとしています。

アイデアは、初期化TableViewControllerNSMutableArray使用したクラスがあるということです。クラスTableViewからこの配列を再初期化する必要があります。DropDown委任を使用してそれを実行しようとしましたが、まだ実行できませんでした。何か問題がある可能性があります。クラスに渡しTableViewControllerDropDown、オブジェクトを介してテーブルを編集できます。しかし、委任を使用してそれを実現したいと思います。

これが私のTableViewController.h

@protocol TableViewControllerdelegate;
@interface TableViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,MFMessageComposeViewControllerDelegate>
{
    ControllerType controllerType;
}

@property (retain, nonatomic) IBOutlet UITableView *tableView;
@property (retain, nonatomic) NSMutableArray *dataArray;
@property (retain, nonatomic) NSArray *imageArray;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil andType:(ControllerType)type;
- (void)sendSMS: (NSString *) sms;

@end;

これが私のDropDown.h

#import "TableViewController.h"
@interface DropDownExample : UITableViewController <VPPDropDownDelegate, UIActionSheetDelegate> {
@private
    VPPDropDown *_dropDownSelection;
    VPPDropDown *_dropDownSelection1;
    VPPDropDown *_dropDownSelection2;
    VPPDropDown *_dropDownSelection3;
    VPPDropDown *_dropDownSelection4;
    VPPDropDown *_dropDownDisclosure;
    VPPDropDown *_msg;
    VPPDropDown *_dropDownCustom;

    NSIndexPath *_ipToDeselect;
}
+ (bool) uncheck:(UITableViewCell *) cell andData:(NSString *) data;
- (void)reloadData;
@end

そして、これが私のtableviewオブジェクト配列を編集しようとする方法です

            TableViewController *newControll = (TableViewController*)[UIApplication sharedApplication].delegate;
            NSMutableArray *arrayWithInfo = [[NSMutableArray alloc] initWithObjects:AMLocalizedString(@"Status", nil),AMLocalizedString(@"Call", nil),AMLocalizedString(@"Location", nil),AMLocalizedString(@"Control", nil),AMLocalizedString(@"Sim", nil),AMLocalizedString(@"Object", nil),AMLocalizedString(@"Info", nil),nil];
            newControll.dataArray = arrayWithInfo;
            [arrayWithInfo release];
            [newControll.tableView reloadData];

実行していますが、'-[AppDelegate setDataArray:]: unrecognized selector sent to instance このコードに到達した後です。

4

2 に答える 2

1

OK、これが正しいかどうかはわかりませんが、委任とは何か、なぜ委任が必要なのかがようやくわかりました。私のシナリオを読んでいただければ、あなたも理解できると思います。

歴史

以前、私の UITabBar アプリで、ビュー コントローラーの上にカスタム フォーム ビューを重ねて表示し、名前と電子メールを入力したいと考えていました。

後で、別のタブの別のビュー コントローラーの上に同じカスタム オーバーレイを表示する必要もありました。

当時、私は委任が何のためにあるのかよくわかっていなかったので、この問題に取り組むために最初に使用した方法は NSNotificationCenter でした。同じコードを 2 番目のビュー コントローラーに複製し、ボタン プレス イベントに接続しました。

別のタブで 2 番目のビュー コントローラーのボタンを押すと、最初のビュー コントローラーと同じように、カスタム オーバーレイが表示されました。

ただし、ここから問題が始まります。

問題

カスタム フォーム ビューを閉じる必要がありました。そのため、NSNotificationCenter を使用して通知を投稿すると、通知のリスナー コールバック メソッドがカスタム ビューを閉じるように指示されました。

問題は、NSNotificationCenter を使用して、最初のタブと 2 番目のタブの両方のすべてのリスナーが投稿された通知に応答し、その結果、2 番目のビュー コントローラーの上に重ねられたカスタム フォーム ビューだけを閉じるのではなく、すべてのカスタム フォームを閉じたことでした。カスタム ビューがどこから開かれたかに関係なく、ビュー。

私が望んでいたのは、「X」ボタンをタップしてカスタムフォームビューを閉じるときでした。カスタムビューのその単一のインスタンスに対してのみ閉じたいのですが、開いた他のすべてのものではありません。

解決策: 委任

これが私にとって最終的にクリックされた場所です-委任。

委任を使用して、カスタム フォーム ビューの各インスタンスに代理人が誰であるかを伝えます。「X」ボタンをタップしてカスタム ビューを閉じると、開かれた単一のインスタンスだけが閉じられ、他のすべてのインスタンスが閉じられます。ビューコントローラーは変更されませんでした。

いくつかのコード

そうですね、いくつかのコードまで。

これが最善の方法かどうかはわかりませんが(間違っている場合は修正してください)、これが私のやり方です:

// ------------------------------------------------------------
// Custom Form class .h file
// ------------------------------------------------------------

@protocol MyCustomFormDelegate <NSObject>

// if you don't put a @optional before any method, then they become required
// in other words, you must implement these methods
-(void)sendButtonPressed;
-(void)closeButtonPressed;

// example: these two methods here does not need to be implemented
@optional
-(void)optionalMethod1;
-(void)optioinalMethod2;

@end

@interface MyCustomFormView : UIView
{
    ...
    id<MyCustomFormDelegate> delegate;
}

...
@property (nonatomic, retain) id<MyCustomFormDelegate> delegate;

@end


// ------------------------------------------------------------
// Custom Form class .m file
// ------------------------------------------------------------

...

@implementation TruckPickerView

@synthesize delegate;

-(id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];

    if(self)
    {
        ...

        [btnSend addTarget:self selector:@selector(sendEmail) forControlEvent:UIControlEventTouchUpInside];

        ...

        [btnClose addTarget:self selector:@selector(closeForm) forControlEvent:UIControlEventTouchUpInside];
    }

    return self;
}

-(void)sendEmail
{
    // code sends email

    ...

    // ------------------------------------------------------------
    // tell the delegate to execute the delegate callback method
    //
    // note: the implementation will be defined in the 
    // view controller (see below)
    // ------------------------------------------------------------
    [delegate sendButtonPressed];
}

-(void)closeForm
{
    // ------------------------------------------------------------
    // tell the delegate to execute the delgate callback method
    //
    // note: the implementation will be defined in the 
    // view controller (see below)
    // ------------------------------------------------------------
    [delegate closeButtonPressed];
}



// ------------------------------------------------------------
// view controller .h file
// ------------------------------------------------------------

#import "MyCustomFormView.h"

// conform to our delegate protocol
@interface MyViewController <MyCustomFormDelegate>
{
    ...

    // create a single instance of our custom view
    MyCustomFormView *customForm;
}

@property (nonatomic, retain) MyCustomFormView *customForm;


// ------------------------------------------------------------
// view controller .m file
// ------------------------------------------------------------

@synthesize customForm;

-(void)viewDidLoad
{
    customForm = [[MyCustomFormView alloc] initWithFrame:....];

    // tell our custom form this view controller is the delegate
    customForm.delegate = self;

    // only show the custom form when user tap on the designated button
    customForm.hidden = YES;

    [self.view addSubview:customForm];
}

-(void)dealloc
{
    ...
    [customForm release];
    [super dealloc];
}

// helper method to show and hide the custom form
-(void)showForm
{
    customForm.hidden = NO;
}

-(void)hideForm
{
    customForm.hidden = YES;
}

// ------------------------------------------------------------
// implement the two defined required delegate methods
// ------------------------------------------------------------
-(void)sendButtonPressed
{
    ...

    // email has been sent, do something then close 
    // the custom form view afterwards

    ...

    [self hideForm];
}

-(void)closeButtonPressed
{
    // Don't send email, just close the custom form view 
    [self hideForm];
}
于 2012-10-30T14:28:29.090 に答える
0

(エラーが示すように)setDataArray:アプリのデリゲート (AppDelegate クラス) にメッセージを送信しているため、このエラーが発生します。

[UIApplication sharedApplication].delegate;

これにより、アプリのデリゲートが返されます。アプリのデリゲートであるクラスを見つける方法はいくつかありますが、通常は AppDelegate と呼ばれ (あなたの場合のように)、UIApplicationDelegateプロトコルも実装しています。

それをまったく別のクラスに単純にキャストすることはできません。アプリ デリゲートにタイプの ivar またはプロパティがあるTableViewController場合は、アクセサーを使用して取得する必要があります。プロパティの場合は、ドット表記を使用できます。ivar の場合は、ivar を返す getter メソッドを実装するか、代わりにプロパティにすることができます。

// assuming your app delegate has a TableViewController property called myTableViewController.
AppDelegate *appDelegate = (AppDelegate *)[UIApplication sharedApplication].delegate;
TableViewController *tableViewController = appDelegate.myTableViewController;

これでエラーは修正されますが、デリゲート パターンの使用も間違っています。カスタム デリゲートを使用している場所がわかりません。プロトコルを前方宣言しTableViewControllerdelegateますが、その宣言が表示されないか、使用しようとしている場所がわかりません。

于 2012-10-30T13:03:55.770 に答える