0

I have encountered this error when i click on the label at the Master View that leads to the Detail view (which should show the labels as displayed in the data model at ReasonLibrary.

My code:

Master View Controller header

@interface MasterViewController : UIViewController

@property (strong, nonatomic) IBOutletCollection(UILabel) NSArray *reasonLabelViews;

@end

Master View Controller implementation

#import "MasterViewController.h"
#import "DetailViewController.h"
#import "Reasons.h"

@interface MasterViewController ()

@end

@implementation MasterViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    for (NSUInteger index = 0; index < self.reasonLabelViews.count; index++) {

        Reasons *reason = [[Reasons alloc] initWithIndex:index];

        UILabel *reasonLabelView = self.reasonLabelViews[index];

        reasonLabelView.text = reason.reasonsRazao;

    }

}

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

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

    UILabel *reasonLabelView = (UILabel *)[sender view];

    if ([self.reasonLabelViews containsObject:reasonLabelView]) {
        NSUInteger index = [self.reasonLabelViews indexOfObject:reasonLabelView];

        DetailViewController *detailViewController = (DetailViewController *)segue.destinationViewController;

        detailViewController.reason = [[Reasons alloc] initWithIndex:index];
    }
}

- (IBAction)showReasonDetail:(id)sender {
    [self performSegueWithIdentifier:@"showReasonDetail" sender:sender];
}



@end

Detail View Controller header

#import <UIKit/UIKit.h>

@class Reasons;

@interface DetailViewController : UIViewController

@property (strong, nonatomic) Reasons *reason;

@property (weak, nonatomic) IBOutlet UILabel *reasonLabel;

@property (weak, nonatomic) IBOutlet UILabel *motiveLabel;

@property (weak, nonatomic) IBOutlet UILabel *zeroFiveLabel;

@end

Detail View Controller implementation

#import "DetailViewController.h"
#import "Reasons.h"

@interface DetailViewController ()

@end

@implementation DetailViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    if (self.reason) {
        self.reasonLabel.text = self.reason.reasonsRazao;
        self.motiveLabel.text = self.reason.randomFact;
        self.zeroFiveLabel.text = self.reason.reasonsDeZeroACinco;
    }


}

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


@end

ReasonsLibrary header

#import <Foundation/Foundation.h>


extern NSString *const kRazao;
extern NSString *const kMotivo;
extern NSString *const kDeZeroACinco;



@interface ReasonLibrary : NSObject

@property (strong,nonatomic) NSArray *library;

- (NSString *)randomFact;

@end

ReasonsLibrary implementation

#import "ReasonLibrary.h"

@implementation ReasonLibrary

NSString *const kRazao = @"razao";
NSString *const kMotivo = @"motivo";
NSString *const kDeZeroACinco = @"dezeroacinco";

- (instancetype)init
{
    self = [super init];
    if (self) {
        _library = @[@{kRazao: @"Razao 1",
                       kMotivo: @[@"Por que sim",@"Por que demais",@"Por que muito",@"Por que foda",@"Por que top",@"Por que demasiado"],
                       kDeZeroACinco: @"1",
                       },
                     @{kRazao: @"Razao 2",
                       kMotivo: @[@"Por que sim",@"Por que demais",@"Por que muito",@"Por que foda",@"Por que top",@"Por que demasiado"],
                       kDeZeroACinco: @"2",
                       },
                     @{kRazao: @"Razao 3",
                       kMotivo: @[@"Por que sim",@"Por que demais",@"Por que muito",@"Por que foda",@"Por que top",@"Por que demasiado"],
                       kDeZeroACinco: @"3",
                       },
                     @{kRazao: @"Razao 4",
                       kMotivo: @[@"Por que sim",@"Por que demais",@"Por que muito",@"Por que foda",@"Por que top",@"Por que demasiado"],
                       kDeZeroACinco: @"4",
                       },
                     @{kRazao: @"Razao 5",
                       kMotivo: @[@"Por que sim",@"Por que demais",@"Por que muito",@"Por que foda",@"Por que top",@"Por que demasiado"],
                       kDeZeroACinco: @"5",
                       },
                     @{kRazao: @"Razao 6",
                       kMotivo: @[@"Por que sim",@"Por que demais",@"Por que muito",@"Por que foda",@"Por que top",@"Por que demasiado"],
                       kDeZeroACinco: @"6",
                       }

                     ];
    }
    return self;
}

- (NSString *)randomFact {
int random = arc4random_uniform((int)self.library.count);
return [self.library objectAtIndex:random];

} @end

Reasons header

#import <Foundation/Foundation.h>

@interface Reasons : NSObject

@property (strong, nonatomic) NSString *reasonsRazao;
@property (strong, nonatomic) NSString *reasonsMotivo;
@property (strong, nonatomic) NSString *reasonsDeZeroACinco;
@property (strong, nonatomic) NSString *randomFact;

-(instancetype)initWithIndex:(NSUInteger)index;

@end

Reasons implementation

#import "Reasons.h"
#import "ReasonLibrary.h"

@implementation Reasons

-(instancetype)initWithIndex:(NSUInteger)index {

    self = [super init];

    if (self) {

    ReasonLibrary *reasonlibrary = [[ReasonLibrary alloc] init];
    NSArray *library = reasonlibrary.library;

    NSDictionary *reasonsDictionary = library[index];

    _reasonsRazao = [reasonsDictionary objectForKey:kRazao];
    _reasonsMotivo = [reasonsDictionary objectForKey:kMotivo];
    _reasonsDeZeroACinco = [ reasonsDictionary objectForKey:kDeZeroACinco];

    }
    return self;
}

@end
gqmonteiro
  • 37
  • 1
  • 7

2 Answers2

3

Object for key kMotivo is NSArray in your code. You are assigning it to NSString property and afterward to UILabel text property. UILabel tries to call length on NSArray and crash with an exception.

Something like following will work:

NSArray *motives = [reasonsDictionary objectForKey:kMotivo];
if (motives != nil && motives.count > 0) {
  int random = arc4random_uniform(motives.count);
  _reasonsMotivo = motives[random];
}

Code above will take first available motive from array and will assign it to a _reasonsMotivo. It should be inserted instead of following code line:

_reasonsMotivo = [reasonsDictionary objectForKey:kMotivo];
Nikita Leonov
  • 5,684
  • 31
  • 37
  • What do you recommend me to do?? Im kinda lost! I have tried to change the Object for kMotivo to NSArray but i get: "Incompatible pointer types initializing 'NSArray *' with an expression of type NSString – gqmonteiro Jul 02 '15 at 01:20
  • I am not really understand logic of your app. kMotivo is many string. Which of these Strings you want to assign to _reasonsMotivo ? – Nikita Leonov Jul 02 '15 at 01:26
  • @user1370624 I updated with a replacement of code that you need to use – Nikita Leonov Jul 02 '15 at 01:32
  • and where should i insert this? – gqmonteiro Jul 02 '15 at 01:39
  • @user1370624 insert this code block instead of your code line _reasonsMotivo = [reasonsDictionary objectForKey:kMotivo]; – Nikita Leonov Jul 02 '15 at 01:39
  • Thanks a lot for the patience, I managed to add few codes and the app is not crashing anymore. At the ReasonLibrary i inserted a function to get a randomFact at the Motive Array, and at the Display Viewer i call this function when i pass the index. However when i compile, the app is not showing anything, is just blank... any idea? – gqmonteiro Jul 02 '15 at 02:00
  • @user1370624 I have a bad imagination. Can you provide some updated source code and actually screenshot from an app to understand where and what is not showing? Meanwhile Since we resolved the crash, can you set question as answered? Thanks. – Nikita Leonov Jul 02 '15 at 02:02
  • You can find what the app does by clicking at: http://imgur.com/2yY9Ruc I have inserted the following code: - (NSString *)randomFact; at ReasonsLibrary Header ////// - (NSString *)randomFact { int random = arc4random_uniform((int)self.library.count); return [self.library objectAtIndex:random]; at ReasonsLibrary Implementation ////// @property (strong, nonatomic) NSString *randomFact; at Reasons header //////// self.motiveLabel.text = self.reason.randomFact; at Detail View – gqmonteiro Jul 02 '15 at 02:12
  • Ok, and can you send somehow an updated code as well? You can do it as new question if you want. – Nikita Leonov Jul 02 '15 at 02:14
  • I do not see where in your code you assign something to a randomFact in Reason. Likely this is the cause a problem. – Nikita Leonov Jul 02 '15 at 02:22
  • I have created a method to give me a randomFact at the ReasonsLibrary Implementation. It returns a number (that should be the number of the corresponding item at the Motivo array). How can I use this number at the Detail View so I can get the corresponding item at the array Motivo to be shown? – gqmonteiro Jul 02 '15 at 02:26
  • It does not return number, it returns NSString in your code. I think you just need to focus a little bit on what you are writing. In other case it look like I am writing your app, not you are writing it. Crash is addressed, so no you can proceed further with an implementation of your logic. If you will face some problem not related to an application logic that only you know I would be happy to help. – Nikita Leonov Jul 02 '15 at 02:39
  • Of course! You are right. Im new at this, sometimes I dont quite know what I get as returns. What I did was: at the Display View.m: self.motiveLabel.text = [self.reasonLibrary randomFact]; and declared at Display View.h `@class ReasonLibrary and `@property (strong, nonatomic) ReasonLibrary *reasonLibrary; Do you have an idea what am I missing here? – gqmonteiro Jul 02 '15 at 02:46
  • In implementation of RandomFact — [self.library objectAtIndex:random] returns Dictionary, not a String – Nikita Leonov Jul 02 '15 at 02:54
  • Hmm... I see... Well thanks a lot for the help... Im completely stuck, this is an example after i completed a module of a course and I suddenly tried to combine several modules into this app, but i dont know now how can i get a random key for kMotivo :/ thanks tho – gqmonteiro Jul 02 '15 at 03:04
  • @user1370624 I updated my code sample, so it takes not an 0 element, but random one. If you would like to understand more about random functions in iOS I recommend to review following article — http://nshipster.com/random/ – Nikita Leonov Jul 02 '15 at 03:34
  • Thanks for the help, actually i just came here to tell you I tried really hard and managed to get it by myself, i have used at the Detail View: self.motiveLabel.text = self.reason.reasonsMotivo[arc4random_uniform(5)]; – gqmonteiro Jul 02 '15 at 03:42
  • I still have some doubts regarding Objective C, are you interested in maybe we arrange something like setting an 30 minute rate and you help me through Skype with some questions? – gqmonteiro Jul 02 '15 at 03:43
  • @user1370624 My Skype — epam.nikita.leonov – Nikita Leonov Jul 02 '15 at 03:45
0

instead of:

kMotivo: @[@"Por que sim",@"Por que demais",@"Por que muito",@"Por que foda",@"Por que top",@"Por que demasiado"]

use

kMotivo: [[NSArray alloc]initWithObjects:@"Chapter 1",@"Chapter 2",@"Chapter 3",@"Chapter 4",@"Chapter 5",nil]
Jaimy
  • 227
  • 1
  • 8
  • why do you think it will help? Array initialized right with a literals. – Nikita Leonov Jul 02 '15 at 01:39
  • i used it and it worked before. Did it help? if yes, can I get a vote? – Jaimy Jul 02 '15 at 01:41
  • Ok, I will ask differently. Why literal initialization of array is better in compare with the old style initialization of array that you proposed? – Nikita Leonov Jul 02 '15 at 01:42
  • For some reason, when I passed an array that was not initialized like this, it would throw imcompatibility error because an array is just a pointer and NSArray or NSMutableArray are objects and it expects and object. – Jaimy Jul 02 '15 at 01:44
  • you are confusing C static arrays and ObjC literals for arrays. Each time when you see @ it means it is literal (syntactic sugared shortcut) for a definition of some specific object. While C arrays like following {0, 1, 2} for sure are not NSArray objects and will cause problems. – Nikita Leonov Jul 02 '15 at 01:47
  • so as result your answer contains two logically identical definitions of array, but the second one proposed by you just longer. – Nikita Leonov Jul 02 '15 at 01:48