从一个ViewController向另一个ViewController发送文本时,iOS应用程序崩溃

时间:2014-05-21 20:42:02

标签: ios objective-c

我想将用户输入的文本发送到SearchViewController中的itemSearch UITextField到MatchCenterViewController,以便它可以在函数中使用它。

我通过将其IBOutlet放在SearchViewController的标头中,使itemSearch属性公开。然而,在segue期间似乎没有成功发送,因为eBayMatchCenterSearch函数在ShowMatchCenterSegue期间运行时崩溃。

错误讯息:

2014-05-21 15:47:17.785 Parse+Storyboard[8787:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderDictionary initWithObjects:forKeys:count:]: attempt to insert nil object from objects[0]'
*** First throw call stack:
(
    0   CoreFoundation                      0x02a881e4 __exceptionPreprocess + 180
    1   libobjc.A.dylib                     0x026468e5 objc_exception_throw + 44
    2   CoreFoundation                      0x02a4e376 -[__NSPlaceholderDictionary initWithObjects:forKeys:count:] + 390
    3   CoreFoundation                      0x02a7bc29 +[NSDictionary dictionaryWithObjects:forKeys:count:] + 73
    4   Parse+Storyboard                    0x00004c09 -[MatchCenterViewController viewDidLoad] + 329
    5   UIKit                               0x0142533d -[UIViewController loadViewIfRequired] + 696
    6   UIKit                               0x014255d9 -[UIViewController view] + 35
    7   UIKit                               0x0143f942 -[UINavigationController _startCustomTransition:] + 778
    8   UIKit                               0x0144c8f7 -[UINavigationController _startDeferredTransitionIfNeeded:] + 688
    9   UIKit                               0x0144d4e9 -[UINavigationController __viewWillLayoutSubviews] + 57
    10  UIKit                               0x0158e0d1 -[UILayoutContainerView layoutSubviews] + 213
    11  UIKit                               0x01375964 -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 355
    12  libobjc.A.dylib                     0x0265882b -[NSObject performSelector:withObject:] + 70
    13  QuartzCore                          0x0064b45a -[CALayer layoutSublayers] + 148
    14  QuartzCore                          0x0063f244 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
    15  QuartzCore                          0x0063f0b0 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 26
    16  QuartzCore                          0x005a57fa _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
    17  QuartzCore                          0x005a6b85 _ZN2CA11Transaction6commitEv + 393
    18  QuartzCore                          0x005a7258 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 92
    19  CoreFoundation                      0x02a5036e __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 30
    20  CoreFoundation                      0x02a502bf __CFRunLoopDoObservers + 399
    21  CoreFoundation                      0x02a2e254 __CFRunLoopRun + 1076
    22  CoreFoundation                      0x02a2d9d3 CFRunLoopRunSpecific + 467
    23  CoreFoundation                      0x02a2d7eb CFRunLoopRunInMode + 123
    24  GraphicsServices                    0x02ce55ee GSEventRunModal + 192
    25  GraphicsServices                    0x02ce542b GSEventRun + 104
    26  UIKit                               0x01306f9b UIApplicationMain + 1225
    27  Parse+Storyboard                    0x00002b0d main + 141
    28  libdyld.dylib                       0x038e2701 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException

SearchViewController.h:

#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import <Parse/PFCloud.h>
#import "CriteriaViewController.h"



@interface SearchViewController : UIViewController

@property (weak, nonatomic) IBOutlet UIButton *nextButtonOutlet;
@property (nonatomic, copy) NSString *topCategory1;
@property (nonatomic, copy) NSString *topCategory2;
@property (nonatomic, copy) NSNumber *topCategoryId1;
@property (nonatomic, copy) NSNumber *topCategoryId2;
@property (weak, nonatomic) IBOutlet UITextField *itemSearch;



@end

SearchViewController.m:

#import "SearchViewController.h"
#import "MatchCenterViewController.h"
#import "SearchCategoryChooserViewController.h"

@interface SearchViewController ()


@property (weak, nonatomic) IBOutlet UIButton *nextButton;

@end

@implementation SearchViewController

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self.nextButtonOutlet addTarget:self action:@selector(nextButton:) forControlEvents:UIControlEventTouchUpInside];
    // Do any additional setup after loading the view.
}

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.
}




- (IBAction)nextButton:(id)sender
{
    if (self.itemSearch.text.length > 0) {
        [PFCloud callFunctionInBackground:@"eBayCategorySearch"
                           withParameters:@{@"item": self.itemSearch.text}
                                    block:^(NSDictionary *result, NSError *error) {
                                        NSLog(@"'%@'", result);

                                       // Parses results

                                            NSArray *resultArray = [result objectForKey:@"results"];

                                                // Number of Top Categories
                                                NSDictionary *dictionary0 = [resultArray objectAtIndex:0];
                                                NSNumber *numberOfTopCategories = [dictionary0 objectForKey:@"Number of top categories"];

                                                // Ids of the Top Categories
                                                NSDictionary *dictionary1 = [resultArray objectAtIndex:1];
                                                NSArray *topCategoryIdsArray = [dictionary1 objectForKey:@"Top category Ids"];

                                                // Names of the Top Categories
                                                NSDictionary *dictionary2 = [resultArray objectAtIndex:2];
                                                NSArray *topCategoryNamesArray = [dictionary2 objectForKey:@"Top category names"];

                                                // Number of Top Categories matching User Categories
                                                NSDictionary *dictionary3 = [resultArray objectAtIndex:3];
                                                NSNumber *numberOfMatches = [dictionary3 objectForKey:@"Number of matches"];

                                                // Names of Top Categories matching User Categories
                                                NSDictionary *dictionary4 = [resultArray objectAtIndex:4];
                                                NSArray *userCategoriesThatMatchSearch = [dictionary4 objectForKey:@"User categories that match search"];

                                                // Defines where each topCategory name will come from
                                                self.topCategory1 = [topCategoryNamesArray objectAtIndex:0];
                                            if ([numberOfTopCategories intValue] == 2) {
                                                self.topCategory2 = [topCategoryNamesArray objectAtIndex:1];
                                            }

                                                // Defines where each topCategory ID will come from
                                                self.topCategoryId1 = [topCategoryIdsArray objectAtIndex:0];
                                            if ([numberOfTopCategories intValue] == 2) {
                                                self.topCategoryId2 = [topCategoryIdsArray objectAtIndex:1];
                                            }


                                        if (!error) {

                                        // Decides which segue is taken based on results

                                            // if 1 match found clear categoryResults and top2 array
                                            if ([numberOfMatches intValue] == 1 ){
                                                [self performSegueWithIdentifier:@"ShowMatchCenterSegue" sender:self];
                                            }

                                            // if 2 matches found
                                            else if ([numberOfMatches intValue] == 2){
                                                [self performSegueWithIdentifier:@"ShowUserCategoryChooserSegue" sender:self];
                                                //default to selected categories criteria  -> send to matchcenter -> clear categoryResults and top2 array
                                            }

                                            // if no matches found, and 1 top category is returned
                                            else if ([numberOfMatches intValue] == 0 && [numberOfTopCategories intValue] == 1) {
                                                [self performSegueWithIdentifier:@"ShowCriteriaSegue" sender:self];
                                            }

                                            // if no matches are found, and 2 top categories are returned
                                            else if ([numberOfMatches intValue] == 0 && [numberOfTopCategories intValue] == 2) {
                                                [self performSegueWithIdentifier:@"ShowSearchCategoryChooserSegue" sender:self];
                                            }

                                        }
                                    }];
    }
}






#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
{

    if ([segue.identifier isEqualToString:@"ShowMatchCenterSegue"]) {
        MatchCenterViewController *controller = (MatchCenterViewController *) segue.destinationViewController;

        // Send over the search query
        controller.itemSearch.text = self.itemSearch.text;
    }


    else if([segue.identifier isEqualToString:@"ShowSearchCategoryChooserSegue"]){

        SearchCategoryChooserViewController *controller = (SearchCategoryChooserViewController *) segue.destinationViewController;

        // Send over the search query as well as both categories to the Category Chooser VC
        controller.itemSearch.text = self.itemSearch.text;
        controller.topCategory1 = self.topCategory1;
        controller.topCategory2 = self.topCategory2;
        controller.topCategoryId1 = self.topCategoryId1;
        controller.topCategoryId2 = self.topCategoryId2;

    }

    else if([segue.identifier isEqualToString:@"ShowCriteriaSegue"]){



        CriteriaViewController *controller = (CriteriaViewController *) segue.destinationViewController;

        // Send over the search query as well as the specific category to CriteriaVC to use
        controller.itemSearch = self.itemSearch.text;
        controller.chosenCategory = self.topCategoryId1;
    }

}


@end

MatchCenterViewController.h:

#import <UIKit/UIKit.h>
#import <Parse/Parse.h>
#import "AsyncImageView.h"
#import "SearchViewController.h"

@interface MatchCenterViewController : UIViewController <UITableViewDataSource>

@property (nonatomic) IBOutlet UITextField *itemSearch;
@property (nonatomic, strong) NSArray *imageURLs;

@end

MatchCenterViewController.m:

#import "MatchCenterViewController.h"
#import <UIKit/UIKit.h>

@interface MatchCenterViewController () <UITableViewDataSource, UITableViewDelegate>


@property (weak, nonatomic) IBOutlet UITableView *matchCenter;
@property (strong, nonatomic) NSArray *itemsArray;

@end

@implementation MatchCenterViewController


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{

    [super viewDidLoad];



    //perform search with criteria just submitted
        [PFCloud callFunctionInBackground:@"eBayMatchCenterSearch"
                           withParameters:@{@"item": self.itemSearch.text,
                                            @"minPrice": @"250",
                                            @"maxPrice": @"400",
                                            @"itemCondition": @"New",
//                                            @"itemLocation": @"US",
                                            }
                                    block:^(NSString *result, NSError *error) {

                                        if (!error) {
                                            NSLog(@"The result is '%@'", result);
                                        }
                                    }];

}

- (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.
 }
 */



@end

1 个答案:

答案 0 :(得分:4)

itemSearchIBOutlet,因此在视图加载之前不会实例化。在prepareForSegue中设置其文本值意味着您要设置nil的文本值。

在目标控制器中创建NSString属性,并在segue期间设置该属性。然后将其复制到itemSearch.text中的viewDidLoad