Detecting UIButton in frame - ios

I have a method that is called once in a while. it creates a button and gives it a frame and adds it on the self.view. The problem is that I don't want these buttons to overlap, so I am using a counter (integer) to keep the count of how many there are. Sometimes the counter goes wrong of +-1 and two buttons appear overlapping.
This is the code:
in my .h
int CountNumberOfBluetoothDevices;
in the .m
- (void) browser:(MCNearbyServiceBrowser *)browser foundPeer:(MCPeerID *)peerID withDiscoveryInfo:(NSDictionary *)info{
NSLog(#"%#", peerID.description);
CountNumberOfBluetoothDevices = CountNumberOfBluetoothDevices + 1;
NSArray *keys = [BluetoothDeviceDictionary allKeys];
for (NSUInteger k = keys.count; k > 0; k--) {
MCPeerID *key = keys[k - 1];
UIButton *btn = BluetoothDeviceDictionary[key];
if ([key.displayName isEqualToString:peerID.displayName]) {
[btn removeFromSuperview];
NSLog(#"REMOVE DOUBLE");
CountNumberOfBluetoothDevices--;
[BluetoothDeviceDictionary removeObjectForKey:key];
}
}
if (CountNumberOfBluetoothDevices == 1) {
BluetoothDeviceButton = [[UIButton alloc] initWithFrame:CGRectMake(130, -200, 55,55)];
}else if (CountNumberOfBluetoothDevices == 2){
BluetoothDeviceButton = [[UIButton alloc] initWithFrame:CGRectMake(240, -200, 55,55)];
}else if (CountNumberOfBluetoothDevices == 3){
BluetoothDeviceButton = [[UIButton alloc] initWithFrame:CGRectMake(130, -125, 55,55)];
}else if (CountNumberOfBluetoothDevices == 4){
BluetoothDeviceButton = [[UIButton alloc] initWithFrame:CGRectMake(240, -125, 55,55)];
}
Is there a better way to detect this?

Don't use upper case variable and/or property names.
Change CountNumberOfBluetoothDevices = CountNumberOfBluetoothDevices + 1; to countNumberOfBluetoothDevices++;
Use [keys count] instead of keys.count.
The -200 in CGRectMake(130, -200, 55,55)]; is very strange an looks like you have some issues with your view hierarchy. Why is it negative?
Instead of this
NSArray *keys = [BluetoothDeviceDictionary allKeys];
for (NSUInteger k = keys.count; k > 0; k--) {
MCPeerID *key = keys[k - 1];
...
}
I would do
for (MCPeerID *key in [bluetoothDeviceDictionary allKeys]) {
...
}

Related

How can I set/get tag value (NSInteger) for UISwitch

I have dynamic UISwitches that I create using the for loop. I give the tag value for each control to have an identity. I want to reach these values ​​later, but I get 0 each time. What I'm doing wrong?
for(int i = 0;i < self.extraArray.count; i++) {
ProductPropertiesModel *model = (ProductPropertiesModel *)[self.extraArray objectAtIndex:i];
UISwitch *switchButton = [[UISwitch alloc] initWithFrame:CGRectZero];
switchButton.translatesAutoresizingMaskIntoConstraints = false;
switchButton.tag = [model Id];
[switchButton setOn:NO];
[self.view addSubview:switchButton];
[switchButton addTarget:self action:#selector(setState:)
forControlEvents:UIControlEventValueChanged];
}
-(void)setState:(id)sender
{
UISwitch *uiswitch = (UISwitch *)sender;
NSInteger tagInteger= uiswitch.tag;
NSLog(#"%#", [NSString stringWithFormat:#"%li",(long)tagInteger]);
}
The tag value is 0, but that is wrong.
I found the problem. I just made a typo. I noticed that I was writing a typo when I was taking json data. I noticed Id writing instead of id.
NSError *jsonError;
self.extraJsonArray = nil;
self.extraJsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&jsonError];
self.extraArray = [[NSMutableArray alloc]init];
for(int j = 0;j < self.extraJsonArray.count;j++){
#try {
//NSInteger *Id = (NSInteger *)[(NSNumber *)[[self.extraJsonArray objectAtIndex:j]objectForKey:#"Id"] integerValue]; Problem is here
NSInteger *Id = (NSInteger *)[(NSNumber *)[[self.extraJsonArray objectAtIndex:j]objectForKey:#"id"] integerValue];
double price = (double)[(NSNumber *)[[self.extraJsonArray objectAtIndex:j] objectForKey:#"price"] doubleValue];
NSString *property =(NSString *)[[self.extraJsonArray objectAtIndex:j] objectForKey:#"property"];
ProductPropertiesModel *model = [[ProductPropertiesModel alloc] init];
[model setId:Id];
[model setProperty:property];
[model setPrice:price];
[model setChecked:#"No"];
[self.extraArray addObject:model];
} #catch (NSException *exception) {
NSLog(#"%#", exception.reason);
} #finally {
}
}
I would recommend instead setting [model id] as tag, you should set array index as tag.
and then later on in the switch control method, you can get the value from array index, using the code.
ProductPropertiesModel *model = (ProductPropertiesModel *)[self.extraArray objectAtIndex:i];
Hope this helps.
Try this:
for (int i =0; i < self.extraArray.count; i++) {
CGRect frame = CGRectMake(x, y, height, width);
UISwitch *switchControl = [[UISwitch alloc] initWithFrame:frame];
//add tag as index
switchControl.tag = i;
[switchControl addTarget:self action:#selector(setState:) forControlEvents: UIControlEventValueChanged];
[switchControl setBackgroundColor:[UIColor clearColor]];
[self.view addSubview:switchControl];
y= y+50.0;
}
- (IBAction) setState: (UISwitch *) sender {
NSLog(#"no.%d %#",sender.tag, sender.on ? #"On" : #"Off");
//use sender.tag , you know which switch you selected
}

UIPopoverController is not so with a color

Does anyone know why is appearing white part? My View is already gray, but gets two white pieces
whites: Arrow and final Popover!
[UPDATE]
this is the code that calls the popover and makes the arrow points to the button that was clicked!
- (void) buttonFilter {
if (viewFilter == #"Artistas") {
content = [self.storyboard instantiateViewControllerWithIdentifier:#"TipoArtistaViewController"]; // MUDAR PARA O NOVO FILTRO DE ARTISTAS
} else if (viewFilter == #"Músicas") {
content = [self.storyboard instantiateViewControllerWithIdentifier:#"CategoriaViewController"];
}
[self callFilter:btnFilter Filter:content];
}
- (void)callFilter:(id)sender Filter:(UIViewController *) content{
self.currentPop = popoverController;
popoverController = [[WYPopoverController alloc] initWithContentViewController:content];
UIButton * bt = (UIButton * )sender;
UIView *view = [bt valueForKey:#"view"];
popoverController.popoverContentSize = CGSizeMake(320, 180);
popoverController.delegate = self;
[popoverController presentPopoverFromRect:view.bounds inView:view permittedArrowDirections:WYPopoverArrowDirectionAny animated:YES];
}
the next is where to mount the session:
//extend and collpase
- (void)setupViewController {
categoriaBD = [categoriaDAO selectCategoria];
self.data = [[NSMutableArray alloc] init];
for (int i = 0; i < [categoriaBD count]; i++)
{
NSMutableDictionary * teste = [categoriaBD objectForKey:[NSString stringWithFormat:#"%i", i]];
ID = [[teste objectForKey:#"1"] integerValue];
subcategoriaBD = [categoriaDAO selectSubCategoriaByCategoriaID:ID];
NSMutableArray* section = [[NSMutableArray alloc] init];
for (int j = 0; j < [subcategoriaBD count]; j++)
{
NSMutableDictionary * subCat = [subcategoriaBD objectForKey:[NSString stringWithFormat:#"%i", j]];
[section addObject:[NSString stringWithFormat:[subCat objectForKey:#"1"]]];
}
[self.data addObject:section];
}
self.headers = [[NSMutableArray alloc] init];
for (int i = 0; i < [categoriaBD count]; i++)
{
NSString *inStr = [NSString stringWithFormat: #"%i", (int)i];
nomeCategoria = [categoriaBD objectForKey:inStr];
UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(5, 5, 310, 40)];
[label setText:[nomeCategoria objectForKey:#"2"]];
UIView* header = [[UIView alloc] init];
[header setBackgroundColor:[UIColor colorWithRed:(226/255.0) green:(226/255.0) blue:(226/255.0) alpha:1]];
[header addSubview:label];
[self.headers addObject:header];
}
}
You can to create a custom UIPopoverBackgroundView subclass that sets the properties of the arrow you want.
popoverController.popoverBackgroundViewClass = [MyPopoverBackgroundView class];

UITableView sorting

I've been brought in on this project where the previous developers made custom table cells and headers by using xib files and then registering the nibs like so:
[self.accountTable registerNib:[UINib nibWithNibName:kNonATITableViewCellLandscapeNib bundle:[NSBundle mainBundle]] forCellReuseIdentifier:kNonATITableViewCellLandscapeIdentifier];
[self.accountTable registerNib:[UINib nibWithNibName:kNonATITableHeaderLandscapeNib bundle:[NSBundle mainBundle]] forCellReuseIdentifier:kNonATITableHeaderLandscapeId];
The header files have buttons in them and uiimageviews. The buttons are for sorting, the uiimageviews for an arrow icon to show you the direction of the sort (asc, desc). All the buttons and imageviews are IBOutlets. All the buttons are linked to an IBAction:
- (IBAction)sortButtonTouched:(id)sender;
The file also has two other properties:
#property (nonatomic, assign) SortType currentSortingOption;
#property (nonatomic, strong) UIButton* btnLastTouched;
Here is sortButtonTouched:
- (IBAction)sortButtonTouched: (UIButton*) buttonTouched {
if (!self.btnLastTouched) {
self.btnLastTouched = buttonTouched;
}
NSString* strFieldToSort;
UIImageView* ivSortImage;
NSArray* arrSortIcons = [[NSArray alloc] initWithObjects:self.ivAccountSort,self.ivNameSort, self.ivAddressSort, self.ivCitySort, self.ivZipSort, self.ivLastCallSort, self.ivMileageSort, nil];
//get the image for the button selected
if (buttonTouched.tag == 0) {
strFieldToSort = #"customerNumber";
ivSortImage = self.ivAccountSort;
} else if (buttonTouched.tag == 1) {
strFieldToSort = #"customerName";
ivSortImage = self.ivNameSort;
} else if (buttonTouched.tag == 2) {
strFieldToSort = #"address";
ivSortImage = self.ivAddressSort;
} else if (buttonTouched.tag == 3) {
strFieldToSort = #"city";
ivSortImage = self.ivCitySort;
} else if (buttonTouched.tag == 4) {
strFieldToSort = #"zip";
ivSortImage = self.ivZipSort;
} else if (buttonTouched.tag == 5) {
strFieldToSort = #"lastCallDate";
ivSortImage = self.ivLastCallSort;
} else if (buttonTouched.tag == 6) {
strFieldToSort = #"mileage";
ivSortImage = self.ivMileageSort;
}
//set the sort option and add icon
if (!self.currentSortingOption) {
self.currentSortingOption = SORT_ASC;
[ivSortImage setImage:[UIImage imageNamed:Ascending_Icon]];
} else {
if (![self.btnLastTouched isEqual:buttonTouched]) {
self.currentSortingOption = SORT_ASC;
[ivSortImage setImage:[UIImage imageNamed:Ascending_Icon]];
} else {
if (self.currentSortingOption == SORT_ASC) {
self.currentSortingOption = SORT_DESC;
[ivSortImage setImage:[UIImage imageNamed:Descending_Icon]];
} else {
self.currentSortingOption = SORT_ASC;
[ivSortImage setImage:[UIImage imageNamed:Ascending_Icon]];
}
}
}
//show and hide
for(int i=0; i<arrSortIcons.count; i++) {
UIImageView* ivThisImage = [arrSortIcons objectAtIndex:i];
if (buttonTouched.tag == i) {
[UIView animateWithDuration:.25 animations:^(void) {
ivThisImage.alpha = 1.0;
}];
} else {
[UIView animateWithDuration:.25 animations:^(void) {
ivThisImage.alpha = 0.0;
}];
}
}
//call back to routing view controller and sort results based on sort order and field selected
NSDictionary* dictUserData = [[NSDictionary alloc] initWithObjectsAndKeys:
#"Sort Non-ATI", #"Action",
strFieldToSort, #"Field To Sort",
[NSNumber numberWithLong:self.currentSortingOption], #"Sortng Option",
nil];
[[NSNotificationCenter defaultCenter] postNotificationName:#"rvc" object:self userInfo:dictUserData];
self.btnLastTouched = buttonTouched;
}
And the notification fires this method:
- (void) sortNonATIResults : (NSDictionary*) dictSortParams {
if (self.arrNonATIResults.count > 0) {
NSString* sortKey = [dictSortParams objectForKey:#"Field To Sort"];
//change the field to sort to match the customerInfo object properties...
NSNumber* numSortType = [dictSortParams objectForKey:#"Sortng Option"];
BOOL isAsc = YES;
if ([numSortType intValue] == 2) {
isAsc = NO;
}
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:isAsc];
NSArray* arrSortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
NSArray* arrSortedNonATIResults = (NSArray*)[self.arrNonATIResults sortedArrayUsingDescriptors:arrSortDescriptors];
self.arrNonATIResults = [arrSortedNonATIResults mutableCopy];
self.arrDatasource = self.arrNonATIResults;
[self.accountTable reloadData];
}
}
There are two problems right now. The icons are not showing up if the notification is sent. Comment out the notification and they function as expected. The other problem is that the property currentSortingOption doesn't retain it's value. I think both issues are related but I am not 100% sure. When the tableview is reloaded, does the header get instantiated again? This would make sense to me since then the uiimageviews would be reset with no image and the property would lose it's value and reset to 0 (it is the value of a typedef).
So, I am correct, how can I resolve this and if not, what could be causing the problems?
Thanks
OK, sorry for posting and then solving my problem right away, I guess sometimes you just need to write out the problem to find the solution. All I needed to do was not reload the table but just reload the rows. Here's the updated method:
(void) sortNonATIResults : (NSDictionary*) dictSortParams {
if (self.arrNonATIResults.count > 0) {
NSString* sortKey = [dictSortParams objectForKey:#"Field To Sort"];
//change the field to sort to match the customerInfo object properties...
NSNumber* numSortType = [dictSortParams objectForKey:#"Sortng Option"];
BOOL isAsc = YES;
if ([numSortType intValue] == 2) {
isAsc = NO;
}
NSSortDescriptor* sortDescriptor = [[NSSortDescriptor alloc] initWithKey:sortKey ascending:isAsc];
NSArray* arrSortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
NSArray* arrSortedNonATIResults = (NSArray*)[self.arrNonATIResults sortedArrayUsingDescriptors:arrSortDescriptors];
self.arrNonATIResults = [arrSortedNonATIResults mutableCopy];
self.arrDatasource = self.arrNonATIResults;
dispatch_async(dispatch_get_main_queue(), ^{
NSMutableArray *indexPathArray = [[NSMutableArray alloc] init];
for (NSInteger section = 0; section < [self.accountTable numberOfSections]; ++section)
{
for (NSInteger row = 0; row < [self.accountTable numberOfRowsInSection:section]; ++row)
{
[indexPathArray addObject:[NSIndexPath indexPathForRow:row inSection:section]];
}
}
[self.accountTable reloadRowsAtIndexPaths:indexPathArray withRowAnimation:UITableViewRowAnimationNone];
[self.accountTable scrollsToTop];
});
}
}

Buttons press in specific order in iOS

I want to create an UIViewController with for buttons. I want the user to press that four buttons with specific order. What I have done until now is that i give a random tag number in every button with the following code:
-(void)prepareArray {
self.arary = [[NSMutableArray alloc]init];
while (self.arary.count <4) {
int value = arc4random()%4;
BOOL isFound = [[self.arary filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:#"intValue == %d",value]]] count];
if(!isFound)
[self.arary addObject:[NSNumber numberWithInteger:value]];
}
NSLog(#"%#", arary);
button1.tag = [[arary objectAtIndex:0]intValue];
button2.tag = [[arary objectAtIndex:1]intValue];
button3.tag = [[arary objectAtIndex:2]intValue];
button4.tag = [[arary objectAtIndex:3]intValue];
So my question is: how can I create a method in which I got an order of pressing the buttons from 0 to 3? I tried with case and with if statements and I can not figure this out?
-(IBAction)buttonPressed:(UIButton *)button{
[clickDictionary setObject:[NSString stringWithFormat:#"%d",button.tag] forKey:button.titleLabel.text];
NSLog(#"clickDictionary : %#", clickDictionary);
}
You can write method as above. This method will be called on every button click.
In clickDictionary you will get the button name and its tag.
You can sort this dictionary as per your need.
I solve my problem with the following method. Firstly I create my buttons with a for loop:
for (int count = 0; count < 4; count++)
{
self.theButtons = [UIButton buttonWithType:UIButtonTypeSystem];
self.theButtons = [[UIButton alloc] initWithFrame:CGRectMake(100, y, 100, 40)];
[self.theButtons setTitle:[NSString stringWithFormat:#"Press Me"] forState:UIControlStateNormal];
[self.theButtons setTag:[[data.randomArray objectAtIndex:count]intValue]];
[self.theButtons addTarget:self action:#selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[self.theButtons setBackgroundColor:[UIColor purpleColor]];
[self.buttonArray addObject:theButtons];
[self.view addSubview:theButtons];
y=y+60;
}
and attach the tag for the buttons with:
self.randomArray = [[NSMutableArray alloc]init];
while (self.randomArray.count <4) {
int value = arc4random()%4+1;
BOOL isFound = [[self.randomArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:[NSString stringWithFormat:#"intValue == %d",value]]] count];
if(!isFound)
[self.randomArray addObject:[NSNumber numberWithInteger:value]];
}
Finally if i want to check in which order the user pushed the buttons I create another array:
- (void)buttonClicked:(UIButton*)button
{
NSLog(#"Button %ld clicked.", (long int)[button tag]);
int value = [button tag];
button.hidden = YES;
[buttonArray removeObject:button];
//When user taps a button another array created which stores the button tags
if([addIntArray indexOfObject:[NSNumber numberWithInt:value]] == NSNotFound) {
[addIntArray addObject:[NSNumber numberWithInt:value]];
}
and compare it´s button click with a static array.

UISegmentedControl index

I am trying to list out the selected index of many UISegmentControls. I set 5 of them on 1, 2, 3, 4, 5 respectively, and the result after using this code (in the array) is: 2, 2, 0, 0, 0...
for (UISegmentedControl *seg in segmentArray)
{
NSString* xWrapped = [NSString stringWithFormat:#"%d", seg.selectedSegmentIndex+1];
[difficultyH addObject: xWrapped];
}
Why??
EDIT:
This is how the segments are created:
//segment controll
NSArray *itemArray2 = [NSArray arrayWithObjects: #"very easy", #"easy", #"ok", #"hard", #"challenging", nil];
UISegmentedControl *segmentedControl2 = [[UISegmentedControl alloc] initWithItems:itemArray2];
segmentedControl2.frame = CGRectMake(480, -60, 130, 350);
segmentedControl2.segmentedControlStyle = UISegmentedControlStyleBar;
segmentedControl2.selectedSegmentIndex = val - 1;
[segmentedControl2 addTarget:self action:#selector(segmentedControlHomework:) forControlEvents:UIControlEventValueChanged];
segmentedControl2.transform =
CGAffineTransformRotate(segmentedControl2.transform, degreesToRadians(90));
NSArray *arr = [segmentedControl2 subviews];
for (int i = 0; i < [arr count]; i++) {
UIView *v = (UIView*) [arr objectAtIndex:i];
NSArray *subarr = [v subviews];
for (int j = 0; j < [subarr count]; j++) {
if ([[subarr objectAtIndex:j] isKindOfClass:[UILabel class]]) {
UILabel *l = (UILabel*) [subarr objectAtIndex:j];
l.transform = CGAffineTransformMakeRotation(- M_PI / 2.0); //do the reverse of what Ben did
}
}
}
[image1 addSubview:segmentedControl2];
segmentedControl2.tag = i;
[segmentArray addObject: segmentedControl2];
//segment controll

Resources