Monotouch: Remove all subviews from a view - xamarin.ios

I am trying to remove all the subviews from a UIView. I tried the following to no effect:
for (int i = 0; i < this.Subviews.Length; i++)
{
this.Subviews[i].RemoveFromSuperview ();
}

Just tested this and it worked for me. (Although your code also looks good to me...)
foreach (UIView view in tableView.Subviews) {
view.RemoveFromSuperview();
}
If it doesn't work for you, there might be something that prevents the subviews from being removed.

The problem with your sample is how you built the loop.
When you remove the view at 0, the Subviews array is one element shorter, and element 1 becomes element 0 on the next iteration. Your i variable on the other hand keeps growing, so you end up skipping view 1.

Try forcing a refresh of the view afterward, or invoking the Remove call specifically on the main thread.

If you absolutely need to use an for loop, this will do
for (int i = this.Subviews.Length - 1 ; i > 0 i--)
{
this.Subviews[i].RemoveFromSuperview ();
}

Related

Is it possible to sort a vector of string with std::sort(), based on a complex criteria?

I need to sort a std::vector<std::wstring> which contains folder names, in a such manner that the parent folder is always located after all its children, e.g:
C:\Main\App\QtGraphicalEffects\private
C:\Main\App\QtGraphicalEffects
C:\Main\App\Qt\labs\platform
C:\Main\App\Qt\labs
C:\Main\App\Qt
C:\Main\App
C:\Main\
To reach a such sorting I may use a Bubble Sort algorithm, as the following one:
void BubbleSortDirs(std::vector<std::wstring>& dirs)
{
bool swapped = false;
do
{
swapped = false;
for (std::size_t i = 0; i < dirs.size() - 1; ++i)
// swap positions if first dir is entirely contained in the second
if (dirs[i] != dirs[i + 1] && dirs[i + 1].find(dirs[i]) == 0)
{
std::swap(dirs[i], dirs[i + 1]);
swapped = true;
}
}
while (swapped);
}
This code works well, but I feel that a better solution should exist. So I tried to use the std::sort function in order to optimize my sorting, at least to provide a more elegant solution.
I tried the following implementation:
bool SortDirs(const std::wstring& first, const std::wstring& second)
{
// swap positions if first dir is entirely contained in the second
return (first == second || first.find(second) == 0);
}
...
std::sort(dirs.begin(), dirs.end(), SortDirs);
I expected that std::sort() would provide the same result as the BubbleSortDirs() function, but it wasn't the case and the result failed in several locations. At this point I strongly suspect that std::sort() isn't adapted for a complex sorting criteria like the one I'm trying to apply.
So my questions are:
What is the reason why my call to std::sort doesn't provide the expected result?
Is there a way to achieve the above described sorting using the std::sort() function?
If yes, what am I doing wrong?
If no, is the above BubbleSortDirs() function the best way to achieve a such sorting, or does it exist something better?
I finally resolved my issue this way:
std::sort(dirs.rbegin(), dirs.rend());

How to satisfy C6011 error with dynamically allocated array of structures

We have a heap-allocated array of custom structures that is pointed to by a local pointer. The pointer to the array is checked for nullptr. However, during my loop, VC++ complains that the first attempt to use an indexed entry in the array is "Dereferencing NULL pointer 'ppi'".
I'm having a dumb moment here I think, but there doesn't seem to be any way to satisfy the 6011 warning... how do I correct this scenario?
I have included some snippets of code to briefly illustrate the code in question.
// Previously, SystemInfoObject.PeripheralPortInfo is heap-alloc'd to contain
// multiple PeripheralInfo structures, and
// SystemInfoObject.PeripheralPortInfoCount is adjusted to the number
// of elements.
PeripheralInfo *ppi = nullptr;
ppi = SystemInfoObject.PeripheralPortInfo; // Set our local pointer
if (ppi != nullptr)
{
for (int i = 0; i < SystemInfoObject.PeripheralPortInfoCount; i++)
{
if (_tcsncmp(ppi[i].PortName, _T("\\\\"), 2) == 0) // C6011
{
// Some code
}
}
}
Visual Studio strikes again, I didn't see the loop condition that required certain code later on to change the pointer ppi and the null condition was never re-checked on subsequent loop iterations.
Wish I could delete my question! All set!

"control.Exists" within a loop works for first time and not for second time in coded ui

consider the code
for(i = 0; i < 5; i++)
{
if(control.Exists)
{
mouse.Click(button);
}
}
In this, control is a popup window. for the first time of execution, control.Exists = true and for the second time it is false though the control is present. Why is that so? How to make it to be true?
Thanks in advance.
Programs often draw another copy of a control, it looks identical to the eye but it is different. Hence the second time around the loop control refers to the old version of the control but it is no longer present.
Your code is likely to be equivalent to
for(i = 0; i < 5; i++)
{
if(top.middle.control.Exists)
{
mouse.Click(top.middle.button);
}
}
There may be more levels in the UI Control hierarchy but three is enough for the explaination here.
The normal fix is to find the new copy of the control before using it. So change the code to be
for(i = 0; i < 5; i++)
{
top.middle.Find();
if(top.middle.control.Exists)
{
mouse.Click(top.middle.button);
}
}
If that does not work, because middle is also not available, then use top.Find();.
To learn more about which controls are available or not, try code like this and observe which parts of the screen are highlighted with blue boxes.
for(i = 0; i < 5; i++)
{
top.DrawHighLight();
top.middle.DrawHighLight();
top.middle.control.DrawHighLight();
if(top.middle.control.Exists)
{
mouse.Click(top.middle.button);
}
}
Use TryFind() instead, and set the searchTimeout.
You can use Inspect/UISpy to check the RuntimeId of the control. I think it's kind of controls' version described in AdrianHHH's reply.
But, what confuses me most is that I can use the found control in the first time, in the following loops, Although my application is restarted.

iterating through PictureBoxes in visual c++

I'm programming in visual c++, and I have about 60 pictures (indexed p0...p63). I want to make a loop that goes through all the pictures and change their ImageLocation under some conditions.
I figured the Tag property and one of my attempts was like this:
I tagged my pictures from 0 to 63 and then tried the following:
for(int i=0; i<64; i++)
{
PictureBox->Tag[i]->ImageLocation="possible-.gif";
}
It's not working... I get this error:
syntax error : missing ';' before '->' line: 1514
syntax error : missing ';' before '->' line: 1514
(twice, same line)
What's the right way of doing it?
Thank you!
edit:
OK now I have the pictures in an array. Is there a way to have a common rule for all of them? I want to make a click event for each and every one of the pictures. Is the only way setting a rule for each independently? Or can I set a rule for the array itself by saying something like:
if(Pictureboxes[i]_Clicked)
{
Pictureboxes[i].something = "something else";
}
I found the way to solve it. So I guess I'm gonna answer myself:
I made an array of PictureBoxes:
private: static array<System::Windows::Forms::PictureBox^>^ pictures=(gcnew array<System::Windows::Forms::PictureBox^>(64));
and filled it with the pictures:
pictures[0] = p0;
pictures[1] = p1;
pictures[2] = p2;
...
Then i clicked each of the pictures to create click_events.
In each event i typed this:
int place = (/*pic number*/);
IndexOf(pictures);
This code sends to a function named IndexOf the picture i clicked.
And here is IndexOf():
static System::Void IndexOf(int& place)
{
int flag = 0;
if(pictures[place]->ImageLocation == "possible-.bmp")
{
flag = 1;
/*DO CODE*/
}
if(flag)
/*OTHER CODE*/
}
Now i can do whatever code i want for pictures[i] at /do code/ above.

NSMutableArray goes SIGABRT in multithreaded app... but I _am_ doing #synchronized!

Sorry... shame - I didn't run debug mode so the error showed up on the wrong line. In debug-mode, and showing the right line, the error was a simple "dont access an array outside its bounds"-error (typo - i referred to one array but access was to another)
Why does accessing the count of an NSMutableArray produce SIGABRT when I empty the NSMutableArray from another thread? I thought the #synchronized was supposed to do as it's name implies?
NSMutableArray *sourceImageRepArray;
...
#synchronized(self)
{
NSLog(#"singleton 1 %p", self);
unsigned long count = sourceImageRepArray.count; //SIGABRT here!
...
Don't know how much extra code you want me to share... this is the code that triggers it:
#synchronized([Singleton sharedSingleton])
{
NSLog(#"singleton 2 %p", [Singleton sharedSingleton]);
int i, n;
n = [filenames count];
for(i=0; i<n; i++){
ImageRep *item = [[ImageRep alloc] init];
[item setPath:[filenames objectAtIndex:i]];
[[Singleton sharedSingleton].targetImageRepArray insertObject:item atIndex: [targetImageBrowser indexAtLocationOfDroppedItem]];
[item release];
[[Singleton sharedSingleton] removeImageRepFromArray:[Singleton sharedSingleton].sourceImageRepArray withPath:[filenames objectAtIndex:i]];
}
}
singleton 1 == singleton 2:
2011-02-08 07:22:03.265 Crash[60001:5d03] singleton 1 0x200047680
2011-02-08 07:22:03.433 Crash[60001:a0f] singleton 2 0x200047680
why is it not synchronizing?! What else could be going on?
are you sure your self and [Singleton sharedSingleton] are the same object?
Sorry... shame - I didn't run debug mode so the error showed up on the wrong line. In debug-mode, and showing the right line, the error was a simple "dont access an array outside its bounds"-error (typo - i referred to one array but access was to another)
So the solution to my problem was:
Don't do NSLog-debugging in release, it may mark errors on the wrong lines. (sometimes, in multithreaded apps, I guess?)

Resources