Objects not being deleted?

 

In my indicator I create vertical lines with this code

string line_name = INDI_NAME + "_" + (string)Period() + "_" + (string)time[i];

ObjectCreate(0, line_name, OBJ_VLINE, 0, time[i], NULL);
ObjectSetInteger(0, line_name, OBJPROP_STYLE, line_style);
ObjectSetInteger(0, line_name, OBJPROP_COLOR, line_color);
ObjectSetInteger(0, line_name, OBJPROP_BACK, true);

ObjectSetInteger(0, line_name, OBJPROP_SELECTABLE, false);
ObjectSetInteger(0, line_name, OBJPROP_SELECTED, false);
ObjectSetInteger(0, line_name, OBJPROP_HIDDEN, false);

 These lines are valid only for one timeframe, so I want to delete them when the timeframe changes. This is my OnDeinit where I remove them

void OnDeinit(const int reason) {
    int obj_total = ObjectsTotal();
    for (int i = 0; i < obj_total; i++) {
        const string name = ObjectName(i);
        if (StringLen(name) == 0) {
            continue;
        }
                
        Print(i, " = ", name, " >", StringSubstr(name, 0, INDI_NAME_LEN) ,"< A");
                
        if (StringSubstr(name, 0, INDI_NAME_LEN) == INDI_NAME) {
            Print("delete '", name, "'");

            if (!ObjectDelete(name)) {
                Print("Error: can't remove object >", name,"< code #", GetLastError());
                return;
            }
        }
    }
}

 

The code prints all the names of the objects to delete, but the objects are not deleted and no errors are shown.

What do I do wrong?

 
if (StringCompare(StringSubstr(name, 0, INDI_NAME_LEN), INDI_NAME) == 0) {

I haven't tested this but StringSubstr returns a String. You are trying to compare the returned Substring with INDI_NAME. What you did was comparing two "references" to Strings and not their content.

Explaination:

string str1 = "Hello";

string str2 = "Hello";

str1 is not equal to str2 because they are both having two different references. E.g. the one "Hello" is placed at address 0x0100 while the other might be located at 0x0200. Therefore 0x100 != 0x200 and thus never enters the if statement. If you want to compare the Strings of being equal Text (contents) then you like to try my option. 

 

Your suggestion did not solve the problem :( I have changed my comparison to

const string prefix = StringSubstr(name, 0, INDI_NAME_LEN);
if (StringCompare(prefix, INDI_NAME) == 0) {
...
}

 and the problem is not gone. The name of the objects to delete is printed, but they are not deleted. Something else to try?

 

I have found the solution, but it is very strange. My code is removing most of the objects but not all.

The correction is to loop over obj_total + 1 instead of obj_total. Instead of

for (int i = 0; i < obj_total; i++) { ... }

 one must use

for (int i = 0; i <= obj_total; i++) { ... }

Maybe because ObjectsTotal does not return the total number of the objects, but the highest ID. A bug in the documentation.

 
ale:

Your suggestion did not solve the problem :( I have changed my comparison to [...] and the problem is not gone.

This is absolutely ok. I still urge to use StringCompare here. What I don't know right now is, if MQL4 supports a technology called "Stringpool" (which I know from Java). The Stringpool technology is indeed able to compare two similar Strings by reference AND contents by issuing a simple A == B. This only works for the first 127 (... iirc) Strings in the Pool. Otherwise my explaination stays valid. Every new String referenced (regardless of it's contents) has it's own reference.

 

Count down when deleting

    int obj_total = ObjectsTotal();
    for (int i = 0; i < obj_total; i++) {

 

 change to

    int obj_total = ObjectsTotal();
    for (int i = obj_total-1; i >=0; i--) {

 It may work for you

 

Thank you for all the answers. Based on them and other messages in this forum I use now this code

for (int i = ObjectsTotal()-1; i >= 0; i--) {
        string name = ObjectName(i);

        int pos = StringFind(name, INDI_NAME);
        if (pos == 0) {
                ObjectDelete(name);
        }
}
 
ale: What do I do wrong?
 int obj_total = ObjectsTotal();
    for (int i = 0; i < obj_total; i++) {
        const string name = ObjectName(i);
You must count down when closing/deleting in a position loop. Get in the habit of always counting down. Loops and Closing or Deleting Orders - MQL4 forum
Reason: