I add some UIViews to my view using following method:
[self.view addSubview:myStickerView]; // this line is called every time when I select a button from ScrollView.
So, I can have a lot of myStickerView on my self.view.
Now, when I call this line: [myStickerView removeFromSuperview]; it will remove only my last myStickerView.
How can I remove all UIViews (myStickerView)?
The easiest way would be something like this:
for (UIView *view in self.view.subviews) {
if ([view isKindOfClass:[MYStickerView class]) {
[view removeFromSuperView];
}
}
Or you can store references for all inserted sticker views not to go through every subview
The easiest way would be to have an NSMutableArray property that kept track of your sticker views. When you add a sticker view to your view, add it to the array as well, that way you could do something like this when you wanted to remove all the sticker views
-(void)removeStickerViews
{
for(StickerView *stickerView in self.myStickerViewArray)
{
[stickerView doSomething];
[stickerView removeFromSuperview];
}
[self.myStickerViewArray removeAllObjects];
}
-(void)addStickerView:(StickerView *)inStickerView
{
[self.myStickerViewArray addObject:inStickerView];
[self.view addSubview:inStickerView];
}
The idea of keeping track in an array is fine, but I suggest using the more elegant [myArray makeObjectsPerformSelector:#selector(removeFromSuperview)] to achieve the result.
Related
I have a bunch of UIViews that I subclassed that I have been adding to self.view e.g.:
MySpecialView *myView = [[MySpecialView alloc] init];
[self.view addSubview:myView];
Now I want to remove them all from self.view but only those custom ones. I don't want to remove any of the others (I have some other views with options in them etc). Is there anyway of doing this at all? Can I loop through all the subviews and check their type? Any pointers on this would be great! Thanks!
Try a loop like this
for (UIView *view in self.view.subviews)
{
if ([view isKindOfClass:[MySpecialView class]])
[view removeFromSuperview];
}
This simply iterates through all of the subviews and removes any that are of class MySpecialView.
Swift way
for subview in self.view.subviews {
if subview.isKindOfClass(MyClass) {
// Is that class!
} else if subview.isMemberOfClass(MyClass) {
// Is that class or a subclass of that class!
}
}
I have a category for UIView which contains this method to remove all of its subviews:
- (void)empty {
for (UIView *subview in self.subviews) {
[subview removeFromSuperview];
}
}
and upon profiling my project I see multiple memory leaks all pointing to this code:
[wrapperView empty];
which in turn calls the first method.
I searched on Google and found out a cleaner and better solution using:
[self.subviews makeObjectsPerformSelector:#selector(removeFromSuperview)];
which doesn't create memory leaks.
My question is, why is the old solution creating memory leaks? Aren't the UIView *subviews released at the end of the for loop?
In the first method you are mutating the array while iterating through it, in the second you are just sending a message to each object in the array.
To see this for yourself, replace the first method with
NSArray *subviews = self.subviews.copy;
for (UIView *view in subviews) {
[view removeFromSuperview];
}
This way you are working on a copy of the subviews array.
I'm trying to bringtofront my subview because the delete button keeps disappearing.
#implementation MyCell : UITableViewCell
- (void)layoutSubviews
{
[super layoutSubviews];
for (UIView *subview in self.subviews) {
for (UIView *subview2 in subview.subviews) {
NSLog(#"HERE!");
if ([NSStringFromClass([subview2 class]) isEqualToString:#"UITableViewCellDeleteConfirmationView"]) {
NSLog(#"got inside the if!");
[subview2 sendSubviewToBack:subview];
[subview bringSubviewToFront:subview2];
[self.superview bringSubviewToFront:subview2];
}
}
}
}
#end
I subclassed UITableViewCell. Both the NSLogs are printing so I know it's getting in there, but I've tried all 3 of these methods to put the view in front. Any ideas why this wouldn't be working?
subview2 is a subview of subview, which is a subview of self. The receiver of the sendSubviewToBack: or bringSubviewToFront: message must be the superview of the view given as argument. Therefore only the second one of the calls you make is valid. The correct calls would be
[self.superview bringSubviewToFront:self];
[self bringSubviewToFront:subview];
[subview bringSubviewToFront:subview2];
(And the same for sendSubviewToBack:.)
As for your actual problem, I can't figure out the view hierarchy you are using from the code posted, but it seems that it is incorrect. You should probably not have your custom views as direct subviews of self, but rather as subviews of self.contentView (as per Apple's documentation).
In my app I need to call some UIViews more than once. But in one of my method, i've a code like :
[self addSubview:UIImageView];
But i've read that addsubview method must be call once. So, to let the code how is it, how could I check if it's already on subview ? Like :
if ([UIImageView isOnSubview] == NO)
{
[self addSubview:UIImageView];
}
Because I don't find any method to check this :/
Thank you !
You are probably looking for UIView's -(BOOL)isDescendantOfView:(UIView *)view; taken in UIView class reference.
use this one
for (UIView *subview in [self subviews])
{
NSLog(#"%#", subview);
// ---------- remember one thing there should be one imageview ------
if(![subview isKindOfClass:[UIImageView class]])
{
[self addSubview:UIImageView];
}
}
I have some text edit fields, and also a button to show a uidatepicker.. if I go to the uitextedit, the keyboard appears, but when I click the button, the keyboard is still here...
how can I remove it?
thanks!
You need to use resignFirstResponder, see this similar question.
[myTextField resignFirstResponder];
See this answer for the easiest way to do it: Easy way to dismiss keyboard?
[self.view endEditing:YES];
Call -resignFirstResponder on your currently-editing text field.
There are cases where I don't have direct access to the 'first responder', so I tend to use a different approach.
I have a utility class for the keyboard with, among other functions, this one:
+ (BOOL)dismiss:(UIView *)view
{
if (view.isFirstResponder) {
[view resignFirstResponder];
return YES;
}
for (UIView *subView in view.subviews) {
if ([Keyboard dismiss:subView]) // It's calling itself, just to be perfectly clear
return YES;
}
return NO;
}
This lets me simply call for example: [Keyboard dismiss:self.view] from anywhere within a UIViewController.