0

I am a newbie Objetive C developer and I am trying to fill up a vector which it is a variable property... But It doesn't working, I can not understand why or how to fix it

-(void) setUpLabels:(NSString *) _labels_path {
    // Read the label list
    self.label_strings.clear();
    std::vector<std::string> new_values;
    std::ifstream t;
    t.open([_labels_path UTF8String]);
    std::string line;
    while (t) {
        std::getline(t, line);
        new_values.push_back(line);
    }
    self.label_strings.reserve(new_values.size());
    for (int index = 0; index  < new_values.size(); index++) {
        self.label_strings.push_back(new_values[index]);
    }
    NSLog(@"size=%lu",self.label_strings.size());
    t.close();

}

This is the .h file

@interface AIClassifier: Classifier
@property std::vector<std::string> label_strings;

    - (id) init;
    - (id) initWithParams:(NSString *)model:(NSString *) labels;
@end

The function setUpLabels is not in the file..

All the time is printing size = 0. I tried more simple versions with the same result.

David Hoelzer
  • 15,862
  • 4
  • 48
  • 67
carlos.baez
  • 1,063
  • 2
  • 11
  • 31

1 Answers1

0

One problem with this code is that you use @property and self.label_strings. @property creates a getter method that returns a value of type std::vector<std::string>. This is a value, not a pointer/reference, so it will be a new copy of the underlying object. It means that each time you call self.label_strings.push_back(x) or any other method, it operates on a copy of the initial object (which is always empty).

To solve this use _label_strings instead of self.label_strings, or use an instance variable for label_strings instead of a @property:

@interface AIClassifier: Classifier {
    std::vector<std::string> label_strings;
}
@end

(Note: better move this to be a private instance variable in your .mm file)

If there's no particular reason to use C++ for this task, there are several Objective-C ways to read a file line by line.

If the file is small, you can read it completely into memory and then split into separate lines like here: https://stackoverflow.com/a/4466934/1009546

In Objective-C we use NSArray<NSString*>* instead of std::vector<string>.

Another likely reason you don't get anything is that either the _labels_path file path is wrong or that it doesn't exist on device.

You can set a breakpoint in this function and use Xcode step by step debugger to see what actually is going on and what you have in _labels_path and new_values at the time of execution.

Normally you shouldn't normally have to use C++ in Objective-C, especially not in interfaces. If you make your file ".m", and not ".mm", it will not allow C++ inside (only Objective-C).

Note 1: if you stick with C++, you don't need a second loop. Just assigning self.label_strings = new_values; will copy it (this is C++ magic).

Note 2: always check the file after opening it. In Objective-C you normally have NSError* returned from functions. In C++ you can check the failbit (see open docs example).

Note 3: Ideally use RAII to make sure that the file is closed. In this case t.close(); is not needed, because ifstream destructor will close it (see http://www.cplusplus.com/reference/fstream/ifstream/close/).

battlmonstr
  • 5,841
  • 1
  • 23
  • 33
  • I use C++ because I am working with an example for deep learning in IOS.. They mix C++ and objetive C in the code. It can be painful change all the code to NSArray (but it must be done I will do)... Also, I am sure that I the label_strings exists. In fact, it is iterating for all the loop and saving values but when it prints the size, it returns size=0, it is crazy. I think it is related with the scope of the variable but I am not sure... – carlos.baez May 10 '18 at 12:09
  • Ah... I see. It is because self.label_strings always copies the value. I've edited the answer. Try using `_label_strings` instead. Also note: by convention "_" prefix is used for private instance variables, so the parameter `_labels_path` should be rather called `labelsPath`. – battlmonstr May 10 '18 at 12:30