I have a need to get all labels in current view. is it possible? If yes, please advise how can i realize this?
For example, i need to collect all labels from startup screen, then from currently showing popup and etc.
Thanks!
Here is the way to go----
NSMutableArray *labels = [NSMutableArray array];
for (UIView *v in someSuperview.subviews) {
if ([v isKindOfClass:[UILabel class]]) {
[labels addObject:v];
}
}
Suppose if you want to collect label in an array, you can try this:
for (UIView *subview in self.view.subviews)
{
if(subview isKindOfClass:[UILabel class])
{
[arrayOfLabels addObject:subview];
}
}
If you want it to do by means of accessibilityLabel, here are the steps to get view from given accessibilityLabel. Method viewContainingAccessibilityElement:element is extension method to UIAccessibilityElement class.
UIAccessibilityElement *element = [[UIApplication sharedApplication] accessibilityElementWithLabel:label];
UIView *view = (UIView*)[UIAccessibilityElement viewContainingAccessibilityElement:element];
Let me know if it works
Related
I tried to remove my images one by one; for that it's ok but when I tried to add a new image by my library nothing appear, I think my code removes my UIImageView.
-(IBAction)remove:(id)sender {
for (NSUInteger i = 0; i < [self.imageArray count]; i--) {
UIImageView *view = self.imageArray[i];
for (view in [self.view.subviews reverseObjectEnumerator])
if ([view isKindOfClass:[UIImageView class]]){
[view removeFromSuperview];
break;
}
}
}
If you are simply trying to remove and add UIImageViews from a mutable array, you can use the following the code.
//Create and add items to mutable array
NSMutableArray *arr = [#[] mutableCopy];
[arr addObject:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"myImage1"]]];
[arr addObject:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"myImage2"]]];
[arr addObject:[[UIImageView alloc] initWithImage:[UIImage imageNamed:#"myImage3"]]];
//Create temp array to to hold items to remove
NSMutableArray *arrWithItemsToRemove = [#[] mutableCopy];
for(UIView *view in arr)
if([view isKindOfClass:[UIImageView class]])
[arrWithItemsToRemove addObject:view];
//Remove objects
[arr removeObjectsInArray:arrWithItemsToRemove];
NSLog(#"%#", arr);
There are problems with the code you are showing. I am not sure why you have two for loops, and self.imageArray[i] is not even valid Objective-C.
So I am going to assume that you have a view (self.view) which contains subviews, some of which are UIImageViews, and that these are the views you wish to remove.
I would do it like this:
NSMutableArray* viewsToDelete = [NSMutableArray new];
for(UIView* view in self.view.subViews) {
if([view isKindOfClass:[UIImageView class]){
[viewsTodDelete addObject:view];
}
}
// Now remove these
for(UIImageView* imageView in viewsToDelete){
[imageView removeFromSuperView];
}
Note that [subview removeFromSuperview] will delete the subview from its parents subviews array, and that is a potential source of problems.
I am not sure if my code will solve your original problem, but this code is cleaner and simpler than the code you showed us, so it is a good place to start.
I am trying to get current view open in my code using this code in delegate while handling Push Notification
NSArray *views = window.subviews;
NSLog(#"views: %#", views);
UIView *topview=[views lastObject];
when is click on topview and see using below tool (eye mark) it shows the current view
open .
But when i am try to get its kind of class using below two method none of these work
for(UIView *view in window.subviews)
{
if([view isKindOfClass:[MyClass class]])
{
NSLog(#"view is a MyClass\n");
}
}
or
if ([topview isKindOfClass:[MyClass class]])
{
NSLog(#"topview is a MyClass\n");
}
else
{
NSLog(#"topview is NOT a MyClass\n");
}
How can i get my visible view name of kind of class.
self.navigationController.viewControllers returns a UIViewController* array, not a UIView* array.
So, for your first solution:
for(UIViewController *viewController in self.navigationController.viewControllers)
{
if([viewController.view isKindOfClass:[MyClass class]])
{
NSLog(#"view is a MyClass\n");
}
}
will work.
For the visible UIViewController*, you can use:
UIViewController* viewController = self.navigationController.visibleViewController;
For the topmost view:
UIView* topmostView = [[[[UIApplication sharedApplication] keyWindow] subviews] lastObject];
I have had some problems with checking if all UITextFields where filled in in my UITableView with Custom UITableViewCell classes
I was trying to do something with this sort of code:
for (UITextField* textField in self.view.subviews ){
NSLog(#"Text: %#", textField.text);
}
And this is the error:
-[UITableView text]: unrecognized selector sent to instance 0x10b034400
Oke, so I seem to be trying to get the UITableView say its text value, so that is not good. But how can I get the TableViewCell's TextFields? So I can check if the user filled in everything and it can save the information.
Grz
You need to get reference to UITableViewCell and do the enumeration on cell.contentView, all controls are stored on contentView cell property, not view directly. All course you should do check if the view is type of UITextField if you have some other controls than UITextField on cell.
The other thing is that you are not able to get UITextField reference for the cell which are not visible because they will be most likely dequeued.
This gives you all visible table view cells and you just need to enumerate it:
NSArray *arr = [self.tableView visibleCells];
for (UITableViewCell *cell in arr) {
for (UIView *v in cell.contentView.subviews) {
if ([v isKindOfClass:[UITextField class]]) {
UITextField *textField = (UITextField *) v;
NSLog(#"Text: %#", textField.text);
}
}
}
that because view's subviews are not necessarily UITextField objects, try this:
for (UIView *subview in self.view.subviews //be sure you are looping through the right view){
if ([subview isKindOfClass:[UITextField class]]) {
UITextField *textField = (UITextField *) subview;
NSLog(#"Text: %#", textField.text);
}
}
if it is in iOS 7, Your textfields should be in the first view in Cell's subviews
for (UITextField* textField in self.view.subviews[0] ){
NSLog(#"Text: %#", textField.text);
}
I am having a UIView that has button in it. The buttons are not in some array.
I would like to look at the whole UIView (using for loop) and look for a button by its title, and later remove it.
- (void)removeButtonByTitle:(NSString*)name
{
for (buttons in view) {
// find the button with the name "name" and remove it from the view
}
}
I couldn't find a way to do that without saving their names/pointers to an array.
It's generally preferable to use the tag property for this. Then you can simply find the button with the viewWithTag: method and don't have to adjust your code if you decide to change the button title or localize your app.
If you really need to find a button by its title, you could do it like this:
NSString *buttonTitle = #"name";
UIButton *buttonWithTitle = nil;
for (UIButton *button in view.subviews) {
if (![button isKindOfClass:[UIButton class]]) continue;
if ([[button currentTitle] isEqualToString:buttonTitle]) {
buttonWithTitle = button;
break;
}
}
//do something with the button...
Well you could do it like this:
for (UIView *v in view.subviews)
if ([v isKindOfClass:[UIButton class]] && [[(UIButton *)v currentTitle] isEqualToString:#""])
//remove
But I must say that doesn't sound like a robust solution, your button title could change during localization or it may be different for different states.
Do that:
- (void)removeButtonByTitle:(NSString *)name
{
for (UIView *tempView in self.subviews)
{
if ([tempView isKindOfClass:[UIButton class]]) // make sure it's actually a UIButton
{
UIButton *button = tempView;
if ([button.titleLabel.text isEqualToString:name]) // compare the title
{
[button removeFromSuperview];
}
}
}
}
Check this:
-(void)removeButtonWithTitle:(NSString*)titleString {
NSArray *subViews = [self.view subviews];
[subViews enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
if([obj isKindOfClass:[UIView class]]) {
NSArray *subViewsArray = [(UIView*)obj subviews];
for (int i=0; i<[subViewsArray count]; i++) {
id subViewObj = [subViewsArray objectAtIndex:i];
if([subViewObj isKindOfClass:[UIButton class]] && [[(UIButton*)subViewObj titleLabel].text isEqualToString:titleString]) {
[subViewObj removeFromSuperview];
*stop = YES;
break;
}
}
}
}];
}
I have a class that makes a keyboard toolbar which has "Next", "Previous", and "Done" buttons on it. Is there a way for this class to know (or find out) what objects are on the screen at any time?
E.g., can it see what the current view is and what the text fields on it are, and then be able to resign the first responder?
If you specifically want to resign first responder without the need to known which view is the first responder you can send resignFirstResponder to "nil" like this:
[[UIApplication sharedApplication] sendAction:#selector(resignFirstResponder) to:nil from:nil forEvent:nil];
This is documented behaviour although I cannot find in the docs right now.
Is there a way for this class to know
(or find out) what objects are on the
screen at the time?
Find the momma view and you can iterate through all the objects on the screen (because they will be UIViews too) like this. Note that you may need to add recursion:
for (UIView *view in mommaView.subviews) {
do something to the view
}
You can start at the Window class and go down from there, asking [view respondsTo:#selector(isFirstResponder) && [view isFirstResponder] on each. Some debugging code that I use might come in handy as a template and also while debugging:
+ (void) dumpWindowFrom:(NSString *) fromText {
[self dumpViews:[[UIApplication sharedApplication] keyWindow] from:fromText];
}
void dumpViewsRecursive(UIView* view, NSString *text, NSString *indent)
{
Class cl = [view class];
NSString *classDescription = [cl description];
// while ([cl superclass]) //restore to print superclass list
// {
// cl = [cl superclass];
// classDescription = [classDescription stringByAppendingFormat:#":%#", [cl description]];
// }
if ([text compare:#""] == NSOrderedSame)
NSLog(#"%d: %# %# %#", (int)view, classDescription, NSStringFromCGRect(view.frame), view.hidden ? #"Inv" : #"Vis");
else
NSLog(#"%d: %# %# %# %#", (int)view, text, classDescription, NSStringFromCGRect(view.frame), view.hidden ? #"Inv" : #"Vis");
for (NSUInteger i = 0; i < [view.subviews count]; i++)
{
UIView *subView = [view.subviews objectAtIndex:i];
NSString *newIndent = [[NSString alloc] initWithFormat:#" %#", indent];
NSString *msg = [[NSString alloc] initWithFormat:#"%#%d:", newIndent, i];
dumpViewsRecursive (subView, msg, newIndent);
[msg release];
[newIndent release];
}
}
+ (void) dumpViews: (UIView *) view {
dumpViewsRecursive (( (!view) ? [[UIApplication sharedApplication] keyWindow] : view), #"" ,#"");
}
+ (void) dumpViews: (UIView *) view from:(NSString *) fromText{
dumpViewsRecursive ((!view) ? [[UIApplication sharedApplication] keyWindow] : view, fromText, #"");
}
yes, the methods provided below will be called whenever a textField becomes Active. I think you are looking for
- (BOOL) textFieldShouldReturn:(UITextField *)textField
{
[textField resignFirstResponder];
return 1;
}
or
- (void) textFieldDidBeginEditing:(UITextField *)textField
{
[textField resignFirstResponder];
}
- (void) textFieldDidEndEditing:(UITextField *)textField
{
[textField resignFirstResponder];
}
and if you are looking for a specific textField in your view, you should assign them tags:
textField.tag =1 // for textField 1
textField.tag =2 // for textField 2
// You may check for these tags and then resign specific ones.