Calling UIViews's subviews property increments subview retain count by 1? - uiview

I have this code:
UIView *superView = [[UIView alloc] init];
UIView *subView = [[UIView alloc] init];
[superView addSubview:subView];
[subView release];
NSLog(#"retain before %i", [subView retainCount]);//prints 1
int i = superView.subviews.count ;
NSLog(#"retain after %i", [subView retainCount]);//prints 2
i = superView.subviews.count ;
NSLog(#"retain odd %i", [subView retainCount]);//keeps printing 2
Is this an "expected" behavior ?. If so, what is the underlying logic ?

Related

UIPage Control unable to focus in Accesability mode

I am using UIPageController for switching among pages. But some reason it is unable to focus on page indicator in Accessibility mode. Below are the way I am implementing:
CGRect rect = [self.view bounds];
rect.size.height+=37;
[[self.pageController view] setFrame:rect];
NSArray *subviews = self.pageController.view.subviews;
for (int i=0; i<[subviews count]; i++) {
if ([[subviews objectAtIndex:i] isKindOfClass:[UIPageControl class]])
{
//self.pageControl = (UIPageControl *)[subviews objectAtIndex:i];
UIView *pv = [subviews objectAtIndex:i];
CGRect frame = pv.frame;
[pv removeFromSuperview];
[self.pageControl setFrame:frame];
self.pageControl.isAccessibilityElement = YES;
self.pageControl.accessibilityTraits = UIAccessibilityTraitAdjustable;
self.pageControl.accessibilityHint = #"Page Indicator";
//[self.pageController.view addSubview:self.pageControl];
}
}
UIView *pageControlBaseView = [[UIView alloc] initWithFrame:CGRectMake(0, [Utilities is_iPad] ? PAGECONTROL_POSITION_IPAD: PAGECONTROL_POSITION_IPHONE, PAGECONTROL_BASEVIEW_WIDTH, PAGECONTROL_BASEVIEW_HEIGHT)];
[pageControlBaseView addSubview:self.pageControl];
pageControlBaseView.isAccessibilityElement = YES;
self.pageControl.pageIndicatorTintColor = [UIColor grayColor];
self.pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
[self.view addSubview:pageControlBaseView];

Dynamically change height of UIView in Storyboard based from another UIViews height

Considering the following image, object B needs be dynamic in height based off number of UILabels inside it.
Object B heigh must then effect the height of object C.
I currently have this implemented in storyboard however I am stuck on these two things, What should Object B be made of? (I cannot use a stack view as my deployment target is 7.1)
it needs to have repeating list
[uiview] - [uilabel]
Object C is a UIView and I would like the height of Object B to effect its height? how can I achieve that?
You can use this type of code
int lblY = 10; // As per your requirement
int viewBHT = 50; // As per your requirement
UILabel *lbl;
NSMutableArray *arrLbl = [[NSMutableArray alloc] initWithObjects:#"1",#"1",#"1",#"1",#"1",#"1", nil];
UIView *viewB = [[UIView alloc] init];
[viewB setFrame:CGRectMake(0, viewA.frame.origin.y, self.view.frame.size.width, viewBHT)];
[viewB setBackgroundColor:[UIColor darkGrayColor]];
[self.view addSubview:viewB];
for (int i = 0; i < arrLbl.count; i++)
{
lbl = [[UILabel alloc] initWithFrame:CGRectMake(10, lblY , viewB.frame.size.width - 20, 30)];
[lbl setText:[NSString stringWithFormat:#"Hello %d",i]];
[lbl setBackgroundColor:[UIColor lightGrayColor]];
[viewB addSubview:lbl];
lblY = lblY + lbl.frame.size.height + 10;
}
viewBHT = lbl.frame.size.height + lbl.frame.origin.y + 10;
[viewB setFrame:CGRectMake(0, 80, self.view.frame.size.width, viewBHT)];
UIView *viewC = [[UIView alloc] init];
[viewC setFrame:CGRectMake(0, viewB.frame.origin.y + viewB.frame.size.height + 10, self.view.frame.size.width, 50)];
[viewC setBackgroundColor:[UIColor blueColor]];
[self.view addSubview:viewC];
Hope this will help you..!! :)

selector for multiple uibuttons in uitableviewcell

I'm adding the same selector for multiple UIButtons which are part of a UITableViewCell and it works only for the first one. Am I missing something?
Here's my code:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *d = [tableData objectAtIndex:indexPath.row];
NSArray *answers = [d objectForKey:#"answers"];//array of { id = 35; text = "\U03c4\U03a\U03c0\U03bf\U03c4\U03b1"; }
UILabel *startDate = (UILabel *)[cell viewWithTag:100];
long long startDateEpoch = [[d objectForKey:#"startDate"] longLongValue];
NSDate *sDate = [NSDate dateWithTimeIntervalSince1970:startDateEpoch/1000];
NSDateFormatter *startDateFormatter = [[NSDateFormatter alloc] init];
[startDateFormatter setDateFormat:#"dd/MM/yyyy"];
startDate.text = [startDateFormatter stringFromDate:sDate];
((UILabel *)[cell viewWithTag:101]).text = [d objectForKey:#"subject"];
NSArray *tags = [d objectForKey:#"tags"];
((UILabel *)[cell viewWithTag:102]).text = [tags componentsJoinedByString:#" "];
NSString *imageURL = [d objectForKey:#"media"];
UIImageView *iv = (UIImageView *)[cell viewWithTag:103];
iv.contentMode = UIViewContentModeScaleAspectFit;
[iv sd_setImageWithURL:[NSURL URLWithString:imageURL]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
UIView *buttonsContainer = (UIView *)[cell viewWithTag:104];
for(UIView *vv in buttonsContainer.subviews){
[vv removeFromSuperview];
}
int index = 0;
NSLog(#"buttonsContainer children: %d", buttonsContainer.subviews.count);
for(NSDictionary *answer in answers){
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, index * 40 + (index+1)*5, [UIScreen mainScreen].bounds.size.width, 40)];
v.backgroundColor = [UIColor whiteColor];
CGRect labelFrame = v.frame;
labelFrame.origin.y = 0;
UILabel *l = [[UILabel alloc] initWithFrame:labelFrame];
l.text = (NSString *)[answer objectForKey:#"text"];
l.textAlignment = NSTextAlignmentCenter;
UIView *bottomLine = [[UIView alloc] initWithFrame:CGRectMake(0, v.frame.size.height - 1, v.frame.size.width, 1)];
bottomLine.backgroundColor = [UIColor colorWithRed:238.0/255.0 green:205.0/255.0 blue:103.0/255.0 alpha:1.0];
UIButton *b = [[UIButton alloc] initWithFrame:v.frame];
[b addTarget:self action:#selector(answered:) forControlEvents:UIControlEventTouchUpInside];
[v addSubview:l];
[v addSubview:bottomLine];
[v addSubview:b];
[buttonsContainer addSubview:v];
index++;
}
}
So for example if 4 buttons are added, the selector is called only when I click on the first one. When I click on the other three nothing happens.
EDIT:
adding the answered: code:
- (void)answered:(UIButton *)sender
{
NSLog(#"#answered");
}
ok, I found it. Many cudos to TomSwift since his point gave me the idea to place borders on all the views in order to debug their frames size and origin.
Notice that I give to my buttons the same frame as their superviews, which is wrong since they should not have the same origin. The buttons' origin should be 0,0 since they have the same frame size as their superviews.
lessons learn for noobs like me:
When a button does not work, place borders in order to make sure their frame is within the superview's bounds.
Do not assign the same frame on a view and its subview. It will place it outside of the superview's bounds which in 92% of the cases brings undesirable behaviour.

UIScrollView set its contentOffset default?

I have a scroll view which consists of many of views. These views are placed in the view according to their dynamic size. There is also a delete button on each view which deletes the view from the scrollview, and replace the others accordingly.
But I have a problem, when I delete something scrollview does not stay where I deleted. One row up or down.
This is my deletion code:
-(void) redrawTheList:(id)sender :(NSString*) except{
int tempo = counterRow;
NSMutableDictionary *doctorTemp = [[NSMutableDictionary alloc]initWithDictionary:doctorAddition copyItems:YES];
for(int i = 0; i<=tempo;i++)
{
NSString *dictTempKey = [NSString stringWithFormat:#"row%d",i];
NSMutableArray * tempArray = [doctorTemp objectForKey:dictTempKey];
for(UIView * subview in tempArray)
{
for(UIView * subview2 in [subview subviews])
{
if([subview2 isKindOfClass:[UILabel class]])
{
if([((UILabel*)subview2).text isEqualToString:except])
{
counterRow = i;
tempile = i;
yAxis=5.0+(i*40.0);
}
}
}
}
}
for(int j=tempile;j<=tempo;j++)
{
NSString *dictTempKey2 = [NSString stringWithFormat:#"row%d",j];
NSMutableArray * tempArray = [doctorAddition objectForKey:dictTempKey2];
for(UIView * subview in tempArray)
{
[subview removeFromSuperview];
}
[doctorAddition removeObjectForKey:dictTempKey2];
}
for(int k=tempile;k<=tempo;k++)
{
NSString *dictTempKey3 = [NSString stringWithFormat:#"row%d",k];
NSMutableArray * tempArray2 = [doctorTemp objectForKey:dictTempKey3];
for(UIView * subview in tempArray2)
{
for(UIView * subview2 in [subview subviews])
{
if([subview2 isKindOfClass:[UILabel class]])
{
if(![((UILabel*)subview2).text isEqualToString:except])
{
[self createDoctorBox:((UILabel*)subview2).text];
}
}
}
}
}
}
CreateDoctorBox method;
-(UIView*)createDoctorBox : (NSString*)name {
[addedList addObject:name];
NSString *myString = name;
CGSize stringSize = [myString sizeWithFont:[UIFont fontWithName:#"Helvetica-Bold" size:13]];
UIView *doktorKutu = [[UIView alloc]init];
[doctorList addSubview:doktorKutu];
UIView *doktorKutuBas = [[UIView alloc]initWithFrame:CGRectMake(0, 0, 18, 36)];
[doktorKutuBas setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"doktor_isim_kutu_bas"]]];
[doktorKutu addSubview:doktorKutuBas];
UILabel * doktorKutuGovde = [[UILabel alloc]initWithFrame:CGRectMake(10, 0, stringSize.width+3, 36)];
[doktorKutuGovde setFont:[UIFont fontWithName:#"Helvetica-Bold" size:12]];
[doktorKutuGovde setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"doktor_isim_kutu_1px"]]];
[doktorKutuGovde setUserInteractionEnabled:YES];
[doktorKutuGovde setText:myString];
[doktorKutu addSubview:doktorKutuGovde];
UIView * doktorKutuKic = [[UIView alloc]initWithFrame:CGRectMake(stringSize.width+13, 0, 18, 36)];
[doktorKutuKic setBackgroundColor:[UIColor colorWithPatternImage:[UIImage imageNamed:#"doktor_isim_kutu_kic"]]];
[doktorKutu addSubview:doktorKutuKic];
UIImageView *cancelImage = [[UIImageView alloc]initWithImage:[UIImage imageNamed:#"cikar"]];
cancelImage.frame = CGRectMake(-5,9, 18, 18);
[doktorKutuKic addSubview:cancelImage];
UIButton *cancel = [[UIButton alloc]initWithFrame:CGRectMake(-5,0, 20, 36)];
[cancel setUserInteractionEnabled:YES];
[cancel addTarget:self action:#selector(removeNameFromTheList:) forControlEvents:UIControlEventTouchUpInside];
[doktorKutuKic addSubview:cancel];
UITapGestureRecognizer *singlePress =[[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(handleSinglePress:)];
[doktorKutuGovde addGestureRecognizer:singlePress];
[doktorKutu bringSubviewToFront:cancel];
[doctorCommented addObject:doktorKutu];
[doktorKutuKic bringSubviewToFront:cancel];
[doktorKutu bringSubviewToFront:cancel];
dictRowKey = [NSString stringWithFormat:#"row%d",counterRow];
NSMutableArray *row = [[NSMutableArray alloc]init];
doktorKutu.frame = CGRectMake(5, yAxis, stringSize.width+30, 36);
if([doctorAddition objectForKey:dictRowKey]!=nil)
{
row = (NSMutableArray*)[doctorAddition objectForKey:dictRowKey];
if(row.count>0)
{
int totalWidth = 5;
for(int i=0;i<row.count;i++)
{
totalWidth = totalWidth + ((UIView*)[row objectAtIndex:i]).frame.size.width+5;
}
if(totalWidth+stringSize.width<520)
{
doktorKutu.frame = CGRectMake(totalWidth, yAxis, stringSize.width+30, 36);
[row addObject:doktorKutu];
[doctorAddition removeObjectForKey:dictRowKey];
[doctorAddition setObject:row forKey:dictRowKey];
}
else
{
doktorKutu.frame = CGRectMake(5, yAxis+40, stringSize.width+30, 36);
yAxis= yAxis + 40.0;
counterRow++;
dictRowKey = [NSString stringWithFormat:#"row%d",counterRow];
row = [[NSMutableArray alloc]init];
[row addObject:doktorKutu];
[doctorAddition setObject:row forKey:dictRowKey];
}
}
}
else
{
[row addObject:doktorKutu];
[doctorAddition setObject:row forKey:dictRowKey];
}
[doctorList setContentSize:CGSizeMake(10, 36+(counterRow*41))];
return doktorKutu;
}
its because when your function " createDoctorBox " call, there may be you have changed a scrollview properties. Please check there.
in your code [doctorList setContentSize:CGSizeMake(10, 36+(counterRow*41))]; its reset the contentOffset of the UIScrollView. if you want to stay on position of delete button, then below that line, set the delete button point as contentOffset of UIScrollView.
Example code:
[doctorList setContentSize:CGSizeMake(10, 36+(counterRow*41))];
doctorList.contentOffset:CGMakePoint(0,deleteBtn.frame.origin.y);
if its help then please vote for me.

UITapGestureRecognizer on multiple UIView (scrollview subviews)

I have set a scrollview and a bench of UIView (scrollview subviews) with gestures on them:
for (id element in array) {
CustomView *view = [[CustomView alloc] init];
[view setFrame:CGRectMake(x, 16, self.view.frame.size.width, self.view.frame.size.height)];
[self.scrollView setContentSize:CGSizeMake(scrollContentSizeWidth, self.scrollView.frame.size.height)];
UITapGestureRecognizer *tap =
[[UITapGestureRecognizer alloc] initWithTarget:self
action:#selector(selectView:)];
[self.view setTag:[[element valueForKey:#"Id"] integerValue]];
[self.view addGestureRecognizer:tap];
view.userInteractionEnabled = YES;
[self.scrollView addSubview:view];
scrollContentSizeWidth +=110;
x += 110;
}
The called method when a view is touched:
-(void)selectView:(UITapGestureRecognizer *)recognizer{
NSLog(#"id : %i",recognizer.view.tag);//always last assigned value in the loop above
}
So how to fix that? UITapGestureRecognizer seems to be affected to the last view only.
replace this line
[self.view addGestureRecognizer:tap];
with this
[view addGestureRecognizer:tap];

Resources