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..
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
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.
I have been doing an Project for IOS which is written in Objective C. Theres a requirement where i have to put a Button or Label below a table view which kind of act as an Dialog like view over an WebView. There is already an header view embedded into the table view, its work well, but when i try to place the button or label below the table view using Storyboard its not working as expected it actually not positioning below the TableView. Below is the image how my View is laid out :
This is how it looks currently :
Below is the code for my view controller :
ViewController.h:
#import "FlatUIKit.h"
#interface NothiViewController : UIViewController
{
IBOutlet UIWebView *mainWebView;
IBOutlet UISegmentedControl *segmentControl;
IBOutlet UIView *viewNothiPermittedUsers;
IBOutlet UILabel *labelTitleNothiPermittedUsers;
IBOutlet UITableView *tableViewNothiPermittedUsers;
}
#property (nonatomic,strong) NSArray *arrNothiPermittedUsers;
#property(nonatomic,retain) ModelNothi *currentModelNothi;
- (void)updateRightBar:(BOOL)all;
#end
#interface CellNothiPermittedUserList : UITableViewCell
{
}
#property (nonatomic, strong) IBOutlet UILabel *labelUserName;
#property (nonatomic, strong) IBOutlet FUIButton *buttonSend;
#end
ViewController.m:
#interface NothiViewController ()<UIWebViewDelegate,CustomAlertViewDelegate>
{
RequestNothiActionApiType currentNothiActionApiType;
AlertType currentAlertType;
}
#property(nonatomic,strong)NSData *dataNotangsho;
#property(nonatomic,strong)NSData *dataPotrangsho;
#end
#implementation NothiViewController
#synthesize currentModelNothi;
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.view.backgroundColor = APP_VIEW_BACKGROUND_COLOR;
mainWebView.delegate = self;
mainWebView.backgroundColor = UIColor.clearColor;
mainWebView.opaque = YES;
mainWebView.scalesPageToFit = YES;
UIFont *font = [UIFont systemFontOfSize:16.0f];
NSDictionary *attributes = [NSDictionary dictionaryWithObject:font
forKey:NSFontAttributeName];
[segmentControl setTitleTextAttributes:attributes
forState:UIControlStateNormal];
segmentControl.tintColor = COLOR_LOGIN_BUTTON;
self.dataNotangsho = nil;
self.dataPotrangsho = nil;
currentNothiActionApiType = API_TYPE_NOTANGSHO;
NSDictionary *params = #{#"data_ref": #"api",
#"api_key": API_KEY,
#"user_designation": [AppSupporter sharedInstance].currentDesignationID};
NSString *api = [NSString stringWithFormat:#"%#/%#",API_NOTHI_NOTANGSHO,self.currentModelNothi.nothiParts];
CGRect frame = segmentControl.frame;
frame.origin.y = NAV_BAR_HEIGHT + STATUS_BAR_HEIGHT;
segmentControl.frame = frame;
segmentControl.backgroundColor = APP_VIEW_BACKGROUND_COLOR;
// Delay execution of my block for 10 seconds.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, .5 * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
[self connectServer:api withParams:params withProgressMessage:#"তথ্য লোড হচ্ছে, একটু অপেক্ষা করুন..."];
});
viewNothiPermittedUsers.hidden = YES;
viewNothiPermittedUsers.backgroundColor = [UIColor colorWithWhite:0.0F alpha:0.7f];
labelTitleNothiPermittedUsers.backgroundColor = [UIColor lightGrayColor];
[labelTitleNothiPermittedUsers.layer setCornerRadius:8.0f];
labelTitleNothiPermittedUsers.layer.masksToBounds = YES;
labelTitleNothiPermittedUsers.font = [UIFont boldFlatFontOfSize:16.0f];
tableViewNothiPermittedUsers.backgroundColor = [UIColor whiteColor];
tableViewNothiPermittedUsers.tableFooterView = [[UIView alloc] initWithFrame : CGRectZero];
[tableViewNothiPermittedUsers.layer setCornerRadius:8.0f];
tableViewNothiPermittedUsers.layer.masksToBounds = YES;
[[NSNotificationCenter defaultCenter]addObserver:self selector:#selector(notifyNothiForward:) name:EventNothiForward object:nil];
}
Any help would be highly appreciated. Note i am kind of new to IOS programming and the project was written by someone else, which i just got now to extend it, so i am little aware of positioning views at the moment.
I have a problem with one of my views retaining its subviews. The main view displays 'tables' in a restaurant, and loads a subview to display this 'table'.
When the main view is deallocated, the tables seem to remain allocated to memory. I have searched everywhere to try and find a solution to this as I just can't seem to fix it myself.
Firstly the code for the 'table' view:
#protocol tableDelegate <NSObject>
#required
- (void)tablePress:(id)sender;
- (void)tableSelect:(id)sender;
#end
#interface tablevw : UIView
{
CGPoint currentPoint;
}
-(void)changeOrderImage;
-(id)initWithFrame:(CGRect)frame teststring:(NSString *)ts;
#property (nonatomic, weak) IBOutlet UIView *view;
#property (nonatomic, weak) IBOutlet UILabel *numberLabel;
#property (nonatomic, weak) IBOutlet UILabel *nameLabel;
#property (nonatomic) BOOL isEdit;
#property (nonatomic) BOOL hasOrder;
#property (nonatomic, strong) NSMutableDictionary * orderNumbers;
#property (nonatomic) int orderNumber;
#property (nonatomic, strong) NSString *teststring;
#property (nonatomic, weak) IBOutlet UIImageView *tableImage;
#property (nonatomic, weak) id<tableDelegate> delegate;
#end
And the init method for the view:
- (id)initWithFrame:(CGRect)frame teststring:(NSString *)ts{
self = [super initWithFrame:frame];
if (self) {
orderNumbers = [[NSMutableDictionary alloc]init];
isRemote = FALSE;
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"tabletopRound" ofType:#"png"];
UIImageView * iV =[[UIImageView alloc] initWithImage:[[UIImage alloc] initWithContentsOfFile:filePath]];
self.tableImage= iV;
tableImage.frame = CGRectMake(0, 0, 121, 121);
locked = FALSE;
[self addSubview:tableImage];
UITapGestureRecognizer *doubleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:#selector(doubleTap)];
doubleTapGestureRecognizer.numberOfTapsRequired = 2;
[self addGestureRecognizer:doubleTapGestureRecognizer];
UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(35, 50, 48, 20)];
numberLabel = label;
[numberLabel setTextColor:[UIColor blackColor]];
[numberLabel setBackgroundColor:[UIColor clearColor]];
[numberLabel setText:ts];
[self addSubview:numberLabel];
UILabel * labelTwo = [[UILabel alloc] initWithFrame:CGRectMake(24, 123, 70, 20)];
nameLabel = labelTwo;
[nameLabel setTextColor:[UIColor whiteColor]];
[nameLabel setBackgroundColor:[UIColor clearColor]];
[self addSubview:nameLabel];
self.userInteractionEnabled = YES;
self.tag = [ts intValue];
}
return self;
}
Finally, in the 'main' view the tables are added like so:
NSString *myString = [results stringForColumn:#"table_number"];
tablevw * tableView = [[tablevw alloc] initWithFrame:CGRectMake(x-60.5, y-60.5, 121, 121) teststring:myString];
tableView.delegate = self;
[self.view addSubview: tableView];
The delegate is set to Nil when the main view is dealloced. I have over ridden the dealloc method to log the dealloc calls to me - it is being called on the 'main' view but not on the 'table' view.
Thanks for your help
In the dealloc method try
for (UIView *view in [self.view subviews]) {
[view removeFromSuperview];
}
It would be even better if u can try
[tablevw removeFromSuperview], tablevw = nil;
I can see that your tablevw has a week reference to his delegate and that should be enough for to release the parent, but just for argue sake trie to nil tablevws delegate. Create an array of tablevw instances you created (or tag them as already suggested), then before you release parent remove them from superview, set their delegate to nil and kill the array. See what happenes, maybe that will help...
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..