So I have this problem with using 2 UIPickerView controls in one ViewController. I am using the CountryPicker found here https://github.com/nicklockwood/CountryPicker to show a nice country picker so the user can select his or hers country, and the country code for his or hers phone number. I want to limit the number of countries in one of the pickers and show all countries in the other picker. But when I show the 2 pickers, it seems that the one which has CountryPicker type is actually using the overriden method -countriesOfOperation from the CustomCountryPicker class.
I have tried with the storyboard and then to programatically init the 2 pickers without success. As you can see I've tried to remove the first picker before showing the second one and vice versa, but it won't fix it.
What could be the reason that even that I am setting *countrySelectionPickerView to be CountryPicker, it still uses the overriden method from CustomCountryPicker? So the object is of type CountryPicker, but it still shows the short countries list.
CustomCountryPicker.h
#import <CountryPicker/CountryPicker.h>
#interface CustomCountryPicker : CountryPicker
/// Returns a dictionary of country names, keyed by country code.
+(NSDictionary<NSString *, NSString *> *)countryNamesByCode;
#end
CustomCountryPicker.m
#import "CustomCountryPicker.h"
#implementation CustomCountryPicker
-(instancetype)initWithFrame:(CGRect)frame
{
return [super initWithFrame:frame];
}
+(NSDictionary *)countriesOfOperation
{
NSDictionary *countries = #{ #"DK": #"Denmark",
#"DE": #"Germany",
#"GB": #"Great Britain",
#"FR": #"France",
#"NO": #"Norway",
#"CH": #"Switzerland"
};
return countries;
}
+(NSDictionary *)countryNamesByCode
{
NSDictionary *countries = [self countriesOfOperation];
static NSDictionary *_countryNamesByCode = nil;
if (!_countryNamesByCode)
{
NSMutableDictionary *namesByCode = [NSMutableDictionary dictionary];
for (NSString *code in [NSLocale ISOCountryCodes])
{
if([countries valueForKey:code]) {
NSString *countryName = [[NSLocale currentLocale] displayNameForKey:NSLocaleCountryCode value:code];
//workaround for simulator bug
if (!countryName)
{
countryName = [[NSLocale localeWithLocaleIdentifier:#"en_US"] displayNameForKey:NSLocaleCountryCode value:code];
}
countryName = [countryName stringByAppendingString:#" XXX"];
namesByCode[code] = countryName ?: code;
}
}
_countryNamesByCode = [namesByCode copy];
}
return _countryNamesByCode;
}
SomeViewController.h
#import <CountryPicker/CountryPicker.h>
...
SomeViewController.m
#import "CustomCountryPicker.h"
#interface SomeViewController () <CountryPickerDelegate>
#property (nonatomic, weak) IBOutlet UIView *countryPickerView;
#property (nonatomic, weak) IBOutlet UIView *customCountryPickerView;
#property (nonatomic, strong) CountryPicker *countrySelectionPickerView;
#property (nonatomic, strong) CustomCountryPicker *customCountrySelectionPickerView;
-(IBAction)countrySelection:(id)sender {
[[[UIApplication sharedApplication] keyWindow] endEditing:YES];
UIButton *senderButton = (UIButton *)sender;
if(senderButton.tag == 101) {
[UIView animateWithDuration:0.2 delay:0.0 options:0 animations:^{
self.countryPickerView.hidden = TRUE;
[self.countrySelectionPickerView removeFromSuperview];
[self.customCountrySelectionPickerView removeFromSuperview];
self.customCountrySelectionPickerView = [[CustomCountryPicker alloc] initWithFrame:CGRectMake(0, 44, 375, 216)];
self.customCountrySelectionPickerView.tag = 11;
self.customCountrySelectionPickerView.delegate = self;
[self.customCountryPickerView addSubview:self.customCountrySelectionPickerView];
self.customCountryPickerView.hidden = FALSE;
self.customCountryPickerView.frame = CGRectMake(0, SCREEN_HEIGHT - 260, SCREEN_WIDTH, 260);
} completion:nil];
// update user country
// select user country phone code
} else if(senderButton.tag == 102) {
[UIView animateWithDuration:0.2 delay:0.0 options:0 animations:^{
self.customCountryPickerView.hidden = TRUE;
[self.countrySelectionPickerView removeFromSuperview];
[self.customCountrySelectionPickerView removeFromSuperview];
self.countrySelectionPickerView = [[CountryPicker alloc] initWithFrame:CGRectMake(0, 44, 375, 216)];
self.countrySelectionPickerView.tag = 12;
self.countrySelectionPickerView.delegate = self;
[self.countryPickerView addSubview:self.countrySelectionPickerView];
self.countryPickerView.hidden = FALSE;
self.countryPickerView.frame = CGRectMake(0, SCREEN_HEIGHT - 260, SCREEN_WIDTH, 260);
} completion:nil];
}
This is because the library is using static variables so both your custom subclass and the original CountryPicker share the data. You can remove the static keyword from _countryNames, _countryCodes, _countryNamesByCode and _countryCodesByName and it should work.
Related
I created a NavigationBar and added it to the UIViewController. But after init, the reference turns to nil. I'm new to iOS and OC, I don't know why. Anyone can help? Thank you.
code summary:
#interface ContainerViewController()
#property (nonatomic, retain) UINavigationBar *nav;
#property (nonatomic, retain) UINavigationItem *navItem;
#end
#implementation ContainerViewController
- (instancetype) initWithParams:(NSDictionary *)params {
self = [super init];
if (self) {//...}
return self;
}
- setNavTitle:(NSDictionary *) params {
NSString *title = params[#"title"];
/////////////////////////////////
// here goes wrong
// self.navItem == nil here, why?
/////////////////////////////////
self.navItem.title = title;
}
- (void) viewWillAppear:(Bool)animated {
[super viewWillAppear:NO];
static float navHeight = 64.0;
UIViewController *wvController = [WebView init here];
UINavigationBar *nav = [[UINavigationBar alloc] initWithFrame:CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), navHeight)];
UINavigationItem *navItem = [[UINavigationItem alloc] initWithTitle:title];
nav.items = [NSArray arrayWithObjects: navItem, nil];
///////////////////////////////
// I saved the reference here
//////////////////////////////
[self setNav:nav];
[self setNavItem:navItem];
[self.view addSubview:nav];
[self addChildViewController:wvController];
wvController.view.bounds = CGRectMake(0, 0, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - navHeight);
[self.view addSubview:wvController.view];
[wvController didMoveToParentViewController:self];
}
#end
This will be useful for you, kindly check and do
Tutorial point site is very easy to learn some important UI basics if you are working in Objective C
I'm using a contact picker to grab a string, then pass that string to another view controller, however the UILabel is not updating with the data (or any other string).
In the SlingViewController.m logs below, _taggedFriendsNames is being passed successfully.
Perhaps the issue is because the receiving view controller is trying to update the label on another (SlingshotView) view? I don't think that's the case as I've been updating labels in this way in other methods.
The answer is likely related to updating UILabels in general, but I've had no luck after searching.
Things I've checked with no success:
Updating from the main thread asynchronously
#synthesize the label in SlingshotView
calling setDisplay
Included potentially relevant code below. Thanks in advance for any tips!
SlingViewController.m
-(void)updateFriendsPickedLabel:(id)sender {
NSLog(#"updateFriendsPickedLabel: %#", _taggedFriendsNames); // i see this
slingshotView.friendsPickedLabel.text = #"any string"; // i don't see this
}
SlingViewController.h
#class TBMultiselectController;
#class SlingshotView;
#interface SlingViewController : UIViewController
#property (nonatomic, readonly) SlingshotView *slingshotView;
#property(nonatomic) NSString *taggedFriendsNames;
//for friend picker
-(void)updateFriendsPickedLabel:(id)sender;
#end
MultiSelectViewController.m
- (IBAction) sendButton: (id) sender {
NSMutableString *myString = [[NSMutableString alloc]initWithString:#""];
for (int i=0; i < self.selectedContacts.count; i++) {
Contact *myContact = self.selectedContacts[i];
[myString appendString:[NSString stringWithFormat:#"%# %# ", myContact.firstName, myContact.lastName]];
}
SlingViewController *svc = [[SlingViewController alloc] init];
svc.taggedFriendsNames = myString;
[svc updateFriendsPickedLabel:self];
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
MultiSelectViewController.h
#protocol TBMultiselectControllerDelegate;
#class SlingViewController;
#interface TBMultiselectController : UIViewController <UITableViewDataSource, UITableViewDelegate, UISearchDisplayDelegate, TBContactsGrabberDelegate>
#property (nonatomic, assign) id<TBMultiselectControllerDelegate> delegate;
- (IBAction)sendButton: (id) sender;
#end
#protocol TBMultiselectControllerDelegate <NSObject>
-(void)updateFriendsPickedLabel:(id)sender;
#end
SlingshotView.h
#property (strong, nonatomic) UILabel *friendsPickedLabel;
SlingshotView.m
#synthesize friendsPickedLabel;
...
- (id)initWithFrame:(CGRect)frame {
if ((self = [super initWithFrame:frame])) {
CGRect screenRect = [[UIScreen mainScreen] bounds];
CGRect imageFrame = CGRectMake(0, 0, screenRect.size.width, screenRect.size.height);
contentView = [[UIView alloc] initWithFrame:frame];
[contentView setBackgroundColor:[UIColor whiteColor]];
[contentView setAutoresizingMask:UIViewAutoresizingFlexibleWidth|UIViewAutoresizingFlexibleHeight];
[self addSubview:contentView];
self.friendsPickedLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, screenRect.size.height/2-100, screenRect.size.width-20, 200)];
self.friendsPickedLabel.shadowColor = [UIColor darkGrayColor];
self.friendsPickedLabel.numberOfLines = 0;
self.friendsPickedLabel.shadowOffset = CGSizeMake(0.5, 0.5);
self.friendsPickedLabel.backgroundColor = [[UIColor blackColor] colorWithAlphaComponent:0.0];
[self.friendsPickedLabel setTextAlignment:NSTextAlignmentLeft];
self.friendsPickedLabel.textColor = [UIColor whiteColor];
self.friendsPickedLabel.font = [UIFont fontWithName:#"HelveticaNeue-Bold" size:24];
[contentView addSubview:self.friendsPickedLabel];
You are reallocating this..
SlingViewController *svc = [[SlingViewController alloc] init];
svc.taggedFriendsNames = myString;
[svc updateFriendsPickedLabel:self];
Meaning your
slingshotView.friendsPickedLabel becomes nil..
And you are calling/using the delegate the wrong way, i think it suppose to be
[self.delegate updateFriendsPickedLabel:#"YourData To be Passed"];
From your code you are using the -(void)updateFriendsPickedLabel:(id)sender; inside SlingViewController and not the delegate, you are not implementing the delegate either..
Yes the -(void)updateFriendsPickedLabel:(id)sender; method is called, bacause you are calling it directly from the class..
SlingViewController.h
#interface SlingViewController : UIViewController < TBMultiselectControllerDelegate > // for delegate implementation
#property (nonatomic, readonly) SlingshotView *slingshotView;
#property(nonatomic) NSString *taggedFriendsNames;
//for friend picker
//-(void)updateFriendsPickedLabel:(id)sender;
#end
MultiSelectViewController.m
- (IBAction) sendButton: (id) sender {
NSMutableString *myString = [[NSMutableString alloc]initWithString:#""];
for (int i=0; i < self.selectedContacts.count; i++) {
Contact *myContact = self.selectedContacts[i];
[myString appendString:[NSString stringWithFormat:#"%# %# ", myContact.firstName, myContact.lastName]];
}
/*
SlingViewController *svc = [[SlingViewController alloc] init];
svc.taggedFriendsNames = myString;
[svc updateFriendsPickedLabel:self];
*/
[self.delegate updateFriendsPickedLabel:#"YourString"];
// this will call the method in your implementation class
[self.navigationController dismissViewControllerAnimated:YES completion:nil];
}
Hmm.. I Think you have implemented the delegates the wrong way.
This is suppose to be a comment but its too long..
I would like to start by saying that I am fairly new to iOS programming, so excuse my ignorance.
I have three UITextFields in my CustomLayout. I am asking users to fill in their name, age and sex. I would like two things, if possible. First I would like, as soon as a user hits the return button from the keyboard, the input string to be stored in an NSArray. In addition, the secondary objective is to iterate through the UITextFields when the user hits the same button.
// CustomLayout.h
#interface CustomLayout : UIView {
UITextField *nameField;
UITextField *ageField;
UITextField *sexField;
UILabel *nameLabel;
UILabel *ageLabel;
UILabel *sexLabel;
UIButton *startButton;
}
#property (nonatomic, strong) UITextField *nameField;
#property (nonatomic, strong) UITextField *ageField;
#property (nonatomic, strong) UITextField *sexField;
#property (nonatomic, strong) UILabel *nameLabel;
#property (nonatomic, strong) UILabel *ageLabel;
#property (nonatomic, strong) UILabel *sexLabel;
#property (nonatomic, strong) UIButton *startButton;
-(void)textFieldShouldReturn:(UITextField*)textField;
#end
In the implementation file
//CustomLayout.m
#implementation CustomLayout
#synthesize nameField, ageField, sexField;
#synthesize nameLabel, ageLabel, sexLabel;
#synthesize startButton;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
[self setBackgroundColor:[tkStyle viewBackgroundColor]];
NSString *startButtonLabel = #"Start Experiment";
//alocate and position views
CGRect viewRect;//placeholder rect, reused for each view
//nameLabel and nameField
nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(120, 95, 150, 40)];
nameLabel.textColor = [UIColor colorWithRed:106/256.0 green:180/256.0 blue:150/256.0 alpha:1.0];
nameLabel.font = [UIFont fontWithName:#"Helvetica-Bold" size:25];
nameLabel.backgroundColor=[tkStyle viewBackgroundColor];
nameLabel.text=#"Enter Name:";
nameField = [[UITextField alloc] initWithFrame:CGRectMake(280, 90, 200, 40)];
nameField.textColor = [UIColor colorWithRed:0/256.0 green:84/256.0 blue:129/256.0 alpha:1.0];
nameField.font = [UIFont fontWithName:#"Helvetica-Bold" size:25];
nameField.borderStyle = UITextBorderStyleRoundedRect;
nameField.backgroundColor=[tkStyle viewBackgroundColor];
textFieldShouldReturn:nameField.text;
// same for ageField and sexField
//startButton
viewRect = CGRectMake(250, sexField.frame.origin.y+75, 200, 40);
startButton = [[UIButton alloc] initWithFrame:viewRect];
[startButton setTitle:startButtonLabel forState:UIControlStateNormal];
[startButton setTitleEdgeInsets:UIEdgeInsetsMake(4, 0, 0, 0)];
[startButton setButtonIsActive:true];
//[startButton setOSCAddress:OSCStopPressedString];
[startButton addTarget:self action:#selector(buttonAction:) forControlEvents:UIControlEventTouchDown];
//and so on adjust your view size according to your needs
[self addSubview:nameField];
[self addSubview:ageField];
[self addSubview:sexField];
[self addSubview:nameLabel];
[self addSubview:ageLabel];
[self addSubview:sexLabel];
[self addSubview:startButton];
}
return self;
}
// that should allow for users to hit 'return' button to move through textfields
-(void)textFieldShouldReturn:(UITextField*)textField;
{
//[(NSArray *) userInfoArray addObject:textField.text];
}
// that should change Views as soon as the user presses 'Start Experiment'
-(void)buttonAction:(id)sender
{
[[NSNotificationCenter defaultCenter] postNotificationName:#"startTest" object:self];
}
#end
Any help would be appreciated.
NSDictionary will be a good approach. you can have unique key for each textfield value.
-(void)textFieldShouldReturn:(UITextField*)textField;
should be:
- (BOOL)textFieldShouldReturn:(UITextField*)textField;
Also, don't forget to return TRUE or FALSE (or YES or NO).
To make this work, implement the UITextFieldDelegate protocol in your class.
Put the following line of code in your .m file, above the #implementation:
#interface CustomLayout () <UITextFieldDelegate>
#end
then, set the delegate in your UITextFields with:
nameField.delegate = self;
ageField.delegate = self;
sexField.delegate = self;
This way the textFieldShouldReturn: method will be called when the user presses 'enter'
A couple of things:
Given your delegate methods, I assume you've actually specified the delegate for your three UITextField controls to be the object in which you've implemented these various delegate methods.
If you want to control the behavior of the return key, implement the textFieldShouldReturn method:
- (BOOL)textFieldShouldReturn:(UITextField *)textField
{
if (textField == self.nameField) {
[self.ageField becomeFirstResponder];
} else if (textField == self.ageField) {
[self.sexField becomeFirstResponder];
} else if (textField == self.sexField) {
[textField resignFirstResponder];
[self saveResults];
}
return NO;
}
I'd generally be inclined to do something like the above, where pressing return takes me to the next field, and pressing return on the last one dismisses the keyboard and tries to save the results.
BTW, in IB, I'd make sure that the "return key" setting for the first two control would be "Next", and for the last one, either "Go" or "Done".
Your save routine would simply populate an object with the contents of the three controls:
- (void)saveResults
{
Person *person = [[Person alloc] init];
person.name = self.nameField.text;
if (self.ageField.text) {
person.age = #([self.ageField.text integerValue]);
}
person.sex = self.sexField.text;
// now do whatever you want with this object
}
This obviously assumes that you have a Person class:
#interface Person : NSObject
#property (nonatomic, copy) NSString *name;
#property (nonatomic, strong) NSNumber *age;
#property (nonatomic, copy) NSString *sex;
#end
#implementation Person
#end
If you'd rather use a NSDictionary or NSArray, that's fine, too (make sure you check the text fields are not nil, though), though I personally prefer a well-defined model object like above.
As a refinement, you might want to make sure you only enter numeric values for age (if that's how you want to store the age):
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
if (textField == self.ageField) {
NSCharacterSet *invalid = [[NSCharacterSet characterSetWithCharactersInString:#"1234567890"] invertedSet];
NSRange range = [string rangeOfCharacterFromSet:invalid];
return range.location == NSNotFound; // if non-numeric character not found, return true
}
return YES;
}
I am trying to pass an integer value between UIViewControllers, new to iOS and having problems.
In the UIViewController where the value is being set, there are no problems. But after the value is set NSLog is showing that the value is null in the second UIViewController.
My app is going to use the horizontal slider to determine the length of time in between a UIImage animationDuration in a different UIViewController.
This method is correctly receiving the value from the horizontal slider. I initialized an instance of the "other" UIViewController, imageview.somedata belongs to the other view controller. I know the value is being passed correctly because of the NSLogs below.
- (IBAction) changeButtonPressed:(id)sender {
imageView = [[GTImageView alloc] initWithNibName:#"GTImageView" bundle:nil];
NSLog(#"text value = %#", myTextField);
NSString *textValue = [myTextField text];
int value = [textValue floatValue];
if (value < 0) value = 0;
if (value > 100) value = 100;
mySlider.value = value;
sliderValue = &value;
NSLog(#"sliderValue = %d", *(sliderValue));
myTextField.text = [NSString stringWithFormat:#"%.1d", value];
if ([myTextField canResignFirstResponder]) [myTextField resignFirstResponder];
imageView.someData = *(sliderValue);
NSLog(#"imageView.someData = %d", imageView.someData);
}
This is the top of that implementation file
#import "GTSettingsVC.h"
#import "GTImageView.h"
#import "GTImageView.m"
#interface GTSettingsVC ()
#end
#implementation GTSettingsVC
#synthesize mySlider, myTextField;
#synthesize sliderValue;
That header file
#import "GTImageView.h"
#interface GTSettingsVC : UIViewController
{
IBOutlet UISlider *mySlider;
IBOutlet UITextField *myTextField;
GTImageView *imageView;
int *sliderValue;
}
#property (nonatomic) int *sliderValue;
The header file of the view controller I am trying to send the data to
#import <UIKit/UIKit.h>
#interface GTImageView : UIViewController
{
UIScrollView* scrollView;
UIPageControl* pageControl;
int *someData;
}
#property (nonatomic) int *someData;
The implementation file where I want the variable someData to have the value I gave it in the first controller. NSLog is returning null in this implementation.
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
UIImageView *animatedImageView =
[[UIImageView alloc] i nitWithFrame:CGRectMake(0, 55, 400, 550)];
[self.view addSubview:animatedImageView];
animatedImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"IMG_0052.JPG"],
[UIImage imageNamed:#"IMG_0054.JPG"],
[UIImage imageNamed:#"IMG_0081.JPG"],
nil];
NSLog(#"some data = %#", someData);
// NSLog is returning null
int x = someData;
animatedImageView.animationDuration =
x * [animatedImageView.animationImages count];
[animatedImageView startAnimating];
[self.view addSubview: animatedImageView];
}
I believe you have yet to grasp the concept/idea for View Controller Life Cycle and also Model View Controller (MVC).
The GTImageView that you defined and initiated in changeButtonPressed for your First View Controller (GTSettingsVC) is a local object/instance for GTSettingsVC. If your view controller transition from GTSettingsVC to GTImageView, the data will not pass to there.
Since you are using UINavigationController, I believe you have Segue. The easiest way to pass data for UINavigationController is using prepareForSegue. You will have to prepare the data that you want to pass to the second view controller in this method before the transition to it.
You also make some mistake in GTImageView. someData is not an object, it should not have *. And also try not to use variable, use just the property in stead. It should be:-
#property (nonatomic) int someData;
In GTSettingsVC.M, add the following function:-
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
GTImageView * viewController = segue.destinationViewController;
viewController.someData = 99;
}
In GTImageView.H
#interface GTImageView : UIViewController
{
UIScrollView* scrollView;
UIPageControl* pageControl;
}
#property (nonatomic) int someData;
#end
In viewDidLoad in GTImageView.M
- (void)viewDidLoad
{
[super viewDidLoad];
UIImageView *animatedImageView =
[[UIImageView alloc] initWithFrame:CGRectMake(0,55, 400, 550)];
[self.view addSubview:animatedImageView];
animatedImageView.animationImages = [NSArray arrayWithObjects:
[UIImage imageNamed:#"IMG_0052.JPG"],
[UIImage imageNamed:#"IMG_0054.JPG"],
[UIImage imageNamed:#"IMG_0081.JPG"],
nil];
NSLog(#"some data = %d", self.someData);
int x = self.someData;
animatedImageView.animationDuration =
x * [animatedImageView.animationImages count];
[animatedImageView startAnimating];
[self.view addSubview: animatedImageView];
}
I added a sample project to Github for your reference:-
https://github.com/voyage11/PassingDataTest
There is no need to take int *. Replace it by int and assign the value directly rather than address.
I am trying to apply UITapGestureRecognizer on a UILabel in order to check and open e-mail service. The current UIView is a part of a UIViewController and displayed once user tap on a button.
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#class AddressBook;
#interface ContactInfoUI : UIView <MFMailComposeViewControllerDelegate, UIGestureRecognizerDelegate>{
IBOutlet UIView *view;
UIViewController *mContainerVc;
AddressBook *mAddressBook;
}
#property (nonatomic, retain)UIView *view;
#property (nonatomic, retain)UIViewController *mContainerVc;
#property (nonatomic, retain)AddressBook *mAddressBook;
-(void)addContactInformationFrom:(AddressBook *)addressBook;
#end
.m
#implementation ContactInfoUI
#synthesize view;
#synthesize mContainerVc;
#synthesize mAddressBook;
- (id)init {
self = [super init];
if (self) {
[[NSBundle mainBundle] loadNibNamed:#"ContactInfoView" owner:self options:nil];
self.userInteractionEnabled = YES;
[self addSubview:[self view]];
}
return self;
}
-(void)addContactInformationFrom:(AddressBook *)addressBook{
self.mAddressBook = addressBook;
int y = 20;
CGRect rect = CGRectMake(20, y, 320, 60);
if (![mAddressBook.aEmail isEqualToString:#"-"]) {
UILabel *email = [[UILabel alloc] initWithFrame:rect];
UITapGestureRecognizer *tgr = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(showEmailForm:)];
tgr.delegate = self;
tgr.numberOfTapsRequired = 1;
[email addGestureRecognizer:tgr];
email.userInteractionEnabled = YES;
email.text = mAddressBook.aEmail;
[self addSubview:email];
rect.origin.y += 40;
}
}
-(IBAction)showEmailForm:(id)sender{
// Email Subject
NSString *emailTitle = #"Test Email";
// Email Content
NSString *messageBody = #"Some message";
// To address
NSArray *toRecipents = [NSArray arrayWithObject:#"test#apple.com"];
MFMailComposeViewController *mc = [[MFMailComposeViewController alloc] init];
mc.mailComposeDelegate = self;
[mc setSubject:emailTitle];
[mc setMessageBody:messageBody isHTML:NO];
[mc setToRecipients:toRecipents];
[mContainerVc presentViewController:mc animated:YES completion:NULL];
}
#end
VC.h (part)
#class ContactInfoUI;
#class ElementObject;
#interface ElementDetailsViewController : UIViewController{
ElementObject *element;
IBOutlet ContactInfoUI *infoView;
}
#property(nonatomic, retain) ContactInfoUI *infoView;
- (IBAction)showInfo:(id)sender;
#end
VC.m (part)
- (IBAction)showInfo:(id)sender {
if (infoView == nil) {
infoView = [[ContactInfoUI alloc] init];
infoView.userInteractionEnabled = YES;
infoView.mContainerVc = self;
}
AddressBook *ab = element.getElementAddressBook;
[infoView addContactInformationFrom:ab];
[self.view addSubview:infoView];
infoBtn.selected = YES;
sumBtn.selected = NO;
mapBtn.selected = NO;
infoView.hidden = NO;
staticMapScrView.hidden = YES;
summaryView.hidden = YES;
}
The problem is that, even if I can see the actual UILabel on screen, I can't tap on it and the email function never fired.
I'm glad you figured it. Yeah, if a UI element is smaller than any of the its superviews (all the way up the chain), all UI interaction to that element will be blocked. This goes for labels, buttons, etc..