6596


xcode6  
master-detail-appのテンプレート,coredata使用で始めました。

TableViewControllerで追加ボタンを押すと、右下のViewControllerに移動して  
そのViewControllerの保存ボタンを押すと  
デリゲートによって,insertNewObjectメソッドが呼ばれてTableViewセルを追加。  
というふうにしたいのですが（イメージはアラームアプリの新規登録です)  
うまくいきません。  
![StoryBoardの全体像です。左半分は今回関係ありません。](https://i.stack.imgur.com/dahyG.png)  
![ズームアップ画像](https://i.stack.imgur.com/65xHC.png)  
ViewController.h

[code]

    #import <UIKit/UIKit.h>
    @protocol myProtocol <NSObject>
    -(void)insertNewObject:(id)sender;
    
    @end
    
    
    @interface ViewController : UIViewController
    
    @property (weak, nonatomic) IBOutlet UIBarButtonItem *saveButtom;
    @property(nonatomic,weak)id <myProtocol>  delegate4486;
    
    - (IBAction)saveData:(id)sender;
    - (IBAction)cancel:(id)sender;
    
    @end
    
[/code]

ViewController.m

[code]

    #import "ViewController.h"
    
    @interface ViewController ()
    
    @end
    
    @implementation ViewController
    
    　- (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view.
    　}
    
    　- (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    　}
    
    /*
    #pragma mark - Navigation
    
    // In a storyboard-based application, you will often want to do a little    preparation before navigation
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        // Get the new view controller using [segue destinationViewController].
        // Pass the selected object to the new view controller.
    }
    */
    
    　- (IBAction)saveData:(id)sender {
    
        if([_delegate4486 respondsToSelector:@selector(insertNewObject:)]){
            [_delegate4486 insertNewObject:_saveButtom];
    
        　　}
        [self dismissViewControllerAnimated:YES completion:nil]; }
    
    　- (IBAction)cancel:(id)sender {
        [self dismissViewControllerAnimated:YES completion:nil];
    　}
    
    　@end
    
[/code]

上でif([_delegate4486 responds...])の中身をBreak Pointで設定しても  
ビルドが通ってしまいます。  
MasterViewController.h

[code]

    #import <UIKit/UIKit.h>
    #import <CoreData/CoreData.h>
    #import "ViewController.h"
    
    @interface MasterViewController: UITableViewController <NSFetchedResultsControllerDelegate,myProtocol>
    
     @property (strong, nonatomic) NSFetchedResultsController *fetchedResultsController;
     @property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
    
     @end
    
[/code]

  
ViewController.m

[code]

    #import "MasterViewController.h"
    #import "DetailViewController.h"
    
    　@interface MasterViewController ()
    
    　@end
    
    　@implementation MasterViewController
    
    　- (void)awakeFromNib {
        [super awakeFromNib];
    　}
    
    　- (void)viewDidLoad {
        [super viewDidLoad];
    
        // Do any additional setup after loading the view, typically from a nib.
        self.navigationItem.leftBarButtonItem = self.editButtonItem;
    
        ViewController* viewC=[[ViewController alloc]init];
        viewC.delegate4486 =self;
    }
    
     - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    　}
    
    　- (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
    
        self.tableView.tableFooterView = [[UIView alloc] initWithFrame:CGRectZero];
    　}
    
    　- (void)insertNewObject:(id)sender {
       　 NSManagedObjectContext *context = [self.fetchedResultsController    managedObjectContext];
        　NSEntityDescription *entity = [[self.fetchedResultsController fetchRequest]  entity];
       　 NSManagedObject *newManagedObject = [NSEntityDescription insertNewObjectForEntityForName:[entity name] inManagedObjectContext:context];
    
        // If appropriate, configure the new managed object.
        // Normally you should use accessor methods, but using KVC here avoids the need to add a custom class to the template.
        [newManagedObject setValue:[NSDate date] forKey:@"timeStamp"];
    
        // Save the context.
        NSError *error = nil;
        if (![context save:&error]) {
            // Replace this implementation with code to handle the error appropriately.
            // abort() causes the application to generate a crash log and terminate.   You should not use this function in a shipping application, although it may be useful during development.
            NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
            abort();
        }
    }
    //以下省略
    
[/code]

Break Pointをあえて出るようにして調べてみたところ  
_delegate4486=(id)0x0  
と出たので、これが原因かと思い  
色々とネットで検索しても解決法が分からず  
八方塞がりです。

なぜ上手くいかないのか教えていただけるとありがたいです。


CC BY-SA 3.0
2015-02-16T11:37:39.523
6578
2015-02-21T05:58:08.983
2015-02-21T05:58:08.983
8320
8320
question
ios objective-c uikit
UIViewControllerでUITableViewのdelegateを呼び出すのが上手くいきません。

[code]

    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        // Do any additional setup after loading the view, typically from a nib.
        self.navigationItem.leftBarButtonItem = self.editButtonItem;
    
        ViewController* viewC=[[ViewController alloc]init];
        viewC.delegate4486 = self;
    }
    
[/code]

ここのViewControllerを@propertyやインスタンス変数にしてみたらどうでしょうか？

----- 追記 -----  
すみません、ざっくりすぎたので少しだけ補足させてください（結局ざっくりですが・・・）

[code]

    - (IBAction)saveData:(id)sender  
    
[/code]

を実行する **ViewController** と

[code]

    viewC.delegate4486 = self;
    
[/code]

を設定する **ViewController** を同じインスタンスにしてみてください。


CC BY-SA 3.0
2015-02-16T12:13:07.233
6580
2015-02-16T13:01:59.353
2015-02-16T13:01:59.353
3516
3516
6578
answer


MasterViewController.m

[code]

    #import "MasterViewController.h"
    #import "DetailViewController.h"
    
    @interface MasterViewController ()
    
    @end
    
    @implementation MasterViewController
    
    - (void)awakeFromNib {
        [super awakeFromNib];
    }
    
    - (void)viewDidLoad {
        [super viewDidLoad];
    
        self.navigationItem.leftBarButtonItem = self.editButtonItem;
    // 2行削除
    /*
        ViewController* viewC=[[ViewController alloc]init];
        viewC.delegate4486 =self;
    }
    */
    
    // 中略
    
    #pragma mark - Navigation
    
    - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
        // Segue Identifierは、適宜書きかえてください。
        if ([[segue identifier] isEqualToString: @"Modal") {
            ViewController *controller = (ViewController *)segue.destinationViewController;
            controller.delegate4486 = self;
        } else {
            // ほかの処理
        }
    }
    
    //以下省略
    
[/code]

Stroyboardで、Segueを使って遷移しているのですから、遷移時（prepareForSegue:）に、遷移先のView
Controllerを、Delegateの送り手と設定する（自身をDelegateの受け手とする）のがいいでしょう。

余談：  
Storyboardが進歩していて、遷移先に進むことだけでなく、戻る処理もStoryboardで行えるようになっています。戻る処理を「 **Unwind
Segue** 」と呼んでいますが、それをキーワードにするか、「Storyboard
Exit」とかをキーワードにして、ネット検索すると、情報を得られるでしょう。すくなくともDelegateを使って、遷移先から戻るより、簡潔なプログラムにすることができます。


CC BY-SA 3.0
2015-02-17T00:01:02.520
6596
2015-02-17T07:08:34.590
2015-02-17T07:08:34.590
7362
7362
6578
answer