I am in a situation in which I need to create custom table cells. I have subclassed UITableViewCell:
#interface CustomTableViewCell : UITableViewCell
#property (weak, nonatomic) IBOutlet UIImageView *icon;
#property (weak, nonatomic) IBOutlet UILabel *name;
#property (weak, nonatomic) IBOutlet UILabel *timestamp;
#property (weak, nonatomic) IBOutlet UILabel *email;
#property (weak, nonatomic) IBOutlet UILabel *phone;
...
Icon, name and timestamp will always be required. Email and phone are optional labels. I initially looked into just hiding the 'optional' labels but that does not remove the space that they take up. So I am looking into building this tableviewcell programatically.
2 things:
I cannot find anywhere that builds this programatically with constraints so I am little stumped on how to even get started.
I have created some of it in IB, i.e. since image, name and timestamp will always be there I thought maybe this would be better to put in IB. Then just build out the other labels underneath name and timestamp:
I tried to create a new initMethod:
- (id)initWithUser:(User *) user {
self = [super initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"userCell"];
if (self) {
// configure required stuff
[self.icon setImage:[PersonImage imageForTimestamp:user.timestamp]];
self.name.text = user.name;
self.timestamp.text = user.timestamp;
if (user.email != nil) {
//add email label with constraint tied to timestamp
}
if (user.phone != nil) {
//add phone label with constraint tied to timestamp or email
}
}
return self;
}
I set identifier to userCell in IB. However it does not seem to have my required labels. Can I do this? Is it a good idea? How do I create the labels with the correct position?
Part of your problem is that cells in an table view aren't initd every time. They get dequeued in order to save the overhead of creating a new cell every time. You will customize the data for the cell you're subclassing in -tableView:cellForRowAtIndexPath:.
Related
How to set UILabel text using KVC in iOS ?
Suppose I have following lines of code :
#property (nonatomic, strong) UILabel *nameLabel;
[self setValue:#"someName" forKeyPath:#"nameLabel.text"];
NSLog(#"Using KVC :Output name label - %#",[self valueForKeyPath:#"nameLabel.text"]);
/* Returns nil */
#property (weak, nonatomic) IBOutlet UILabel *nameLabel;
[self setValue:#"Testing123" forKeyPath:#"nameLabel.text"];
See the image below of the storyboard
Seem like I found the fix. UILabel must be on subview, either by dragging and dropping on the storyboard and creating IBOutet or by programatically adding it on the subview.
So, #property (nonatomic, weak) IBOutlet UILabel *nameLabel; did the trick for me.
I have a UIView with two UILabel that I want to reuse in more than one UIViewController. I use storyboard and I assign a custom class alertView:UIView that I declared.
file AlertRemote.h
#interface AlertRemote: UIView
#property (weak, nonatomic) IBOutlet UILabel *label1;
#property (weak, nonatomic) IBOutlet UILabel *label2;
-(void) setTextLabel;
file AlertRemote.m
-(void) setTextLabel{
[ _label1 setText:#"attention..."];
[_label2 setText:#"the program..."];
}
file Controllo.m
//the view present in the storyboard alertView linked to the uiview
#property (strong, nonatomic)IBOutlet AlertRemote *alertView;
#property AlertRemote *alRemView;
[super viewDidLoad];
_alertView=_alRemView; [_alertView setTextLabel];
[_alertView setTextLabel];
if I put some breakpoints inside setTextLabel the code don't works
thanks!!
In order for the custom alert to work, you need to initialise it.
AlertRemote *alRemView;
alRemView = [[AlertRemote alloc]init];
[alRemView setTextLabel];
I think you are not initializing the property alertview. If you are initializing the property alertview then try to set directly with out using alremView.
I'm using a scroll view with 3 views, and I need to place one label that shows up on each view,
the views are on separate view controllers: in view controller.h
#import "PagerViewController.h"
#interface ViewController : PagerViewController {
}
#property (strong, nonatomic) IBOutlet UIView *View1;
#property (strong, nonatomic) IBOutlet UIView *View2;
#property (strong, nonatomic) IBOutlet UIView *View3;
I've placed them as (in ViewController.m)
[self addChildViewController:[self.storyboard instantiateViewControllerWithIdentifier:#"View1"]];
Should I fix an NSString
and Outlet to do this?
I need the labels to move with the scroll not to be separate from each other.
What you want, cannot be done with a single UILabel. You will have to create 3 separate labels and write the logic that will update all of them.
Create the UILabel outlets and write a method something similar to the method below:
- (void)updateLabels:(NSString *)text
{
self.label1.text = text;
self.label2.text = text;
self.label3.text = text;
}
This is just the way UIView's work and you cannot make them draw outside of their bounds.
I suggest you follow up on more iOS basics before going into complex layouts.
If you need to separate these views, a well-maintainable solution could be three separated label and one function (updateLabels:) in which the three label is updated to the same value.
I have created a custom UITableViewCell that contains 3 UILabels and a UIImageView. I am setting this up via storyboards and have a UITableView class that is connected to the table cell. In that class I am wanting to handle the different UI objects and have the option to pass in information from my view controller.
Here is the .h of my table cell view class
#property (retain, nonatomic) IBOutlet GBPathImageView *ProfileThumbnailImageView;
#property (weak, nonatomic) IBOutlet UILabel *profileDisplayNameLabel;
#property (weak, nonatomic) IBOutlet UILabel *profileUniversityNameLabel;
#property (weak, nonatomic) IBOutlet UILabel *profileNumberOfStringsLabel;
#property (strong, nonatomic) NSString *profileDisplayName;
#property (strong, nonatomic) UIImage *profileThumbnailImage;
#property (strong, nonatomic) NSString *profileUniversityName;
#property (nonatomic) NSUInteger profileNumberOfStrings;
- (id)initWithProfileImage:(UIImage *)profileImage
displayName:(NSString *)displayName
universityName:(NSString *)universityName
numberOfUserStrings:(NSUInteger)numberOfStrings;
As you can see I have a property outlet that all of the storyboard objects are connected to. I also have properties for each piece of necessary information. In my view controllers
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
method I am wanting to instantiate this custom cell with information that I pass in. I am wanting to set the information properties with the correct info and have it be setup in the view class.
Here is the code inside the previously mentioned method:
static NSString *cellIdentifier = #"UserProfileCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if ([cell isKindOfClass:[StringrUserTableViewCell class]]) {
StringrUserTableViewCell * userProfileCell = (StringrUserTableViewCell *)cell;
userProfileCell.profileDisplayName = #"Alonso Holmes";
//userProfileCell.profileDisplayNameLabel.text = #"User Name";
}
I have two lines there, one is setting the information property for the name, and I have it in the view's .m file to set its text to that properties name. The problem that is happening is that the profileDisplayName property is null at the time it tries to set that UILabels text. How can I set this information at a time so that it will be there before the cell is loaded or when it's initially loading? You can also see a commented out line where I directly set the text of the UILabel right there. I would prefer not to do it this way because I want to leave the abstraction/logic to the view's class. The image view I setup is custom so it takes more code.
You are trying to set your text in profileDisplayName which is NSString type not a UILabel class. ( see #property (strong, nonatomic) NSString *profileDisplayName; ).
Change your line of code:
here is the problem
userProfileCell.profileDisplayName = #"Alonso Holmes"; //Use Label Object instead of NSString
I have a view controller alertForNeedsClassification as a property in another class, as such:
#interface SCAAppDelegate()
{
HomeScreenViewController * _homeScreenViewController;
NSInteger SCAStatus;
}
#property (strong, nonatomic) PromptClassifyViewController * alertForNeedsClassification;
#end
#implementation SCAAppDelegate
#synthesize alertForNeedsClassification;
#synthesize window = _window;
PromptClassifyViewController's interface looks like this:
#interface PromptClassifyViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *headerTitle;
#property (weak, nonatomic) IBOutlet UITextView *message;
#property (weak, nonatomic) IBOutlet UIButton *notNowButton;
#property (weak, nonatomic) IBOutlet UIButton *classifyButton;
#property (weak, nonatomic) IBOutlet UIImageView *backgroundImageView;
#property (weak, nonatomic) IBOutlet UIView *alertView;
#property NSUInteger tag;
#property (weak, nonatomic) IBOutlet id<PromptClassifyViewControllerDelegate> delegate;
- (void)show;
- (void)showFromView:(UIView *)view;
- (IBAction)show:(id)sender;
- (IBAction)dismiss:(id)sender;
- (IBAction)buttonWasPressed:(id)sender;
- (void)setHeaderTitleWithText:(NSString *)text;
#end
I am trying to change the values of IBOutlets message and headerTitle text, like this:
alertForNeedsClassification = [[PromptClassifyViewController alloc] initWithNibName:#"PromptClassifyViewController" bundle:nil];
//[alertForNeedsClassification setDelegate:self];
self.alertForNeedsClassification.headerTitle.text = #"A title";
alertForNeedsClassification.message.text = #"A message";
Then I show alertForNeedsClassification calling a show method (it's like a custom uialertview, but it doesn't subclass from uialertview).
Thing is, no matter how I change it, the text on alertForNeedsClassification.view is always that which is defined in the nib, ie. I can't change it programmatically.
My custom alert view is based on Jeff LaMarche's design: http://iphonedevelopment.blogspot.com/2010/05/custom-alert-views.html
Any ideas what might be going on?
Please be careful when you allocate and initialize the UIView object, especially if you trying to mix using Nib and dynamically generating objects. The best place is within -(void)awakeFromNib or -(void)viewDidLoad
Also, make sure these methods are called. By using -(id)initWithNibName:bundle: only cannot make sure your view to be loaded. Try -(void)addChildViewController and -(void)addSubview: on parentViewController's view to make sure view is loaded after being initialized.
If the text had to be prepared before being loaded, assign it to separate NSString property within PromptClassifyViewController class. Since this property is independent from view being loaded, you can change it's value BEFORE view is appeared. Make sure this text is used and applied to the headerTitle within -(void)show method.
Since you allocate PromptClassifyViewController and access weak referenced headerTitle from self. alertForNeedsClassification, make sure it's not deallocated right afterward.
Usually, weak option is not used for IBOutlet properties. Though it is used when generating outlet connection code by dragging objects from Interface Builder. Try testing your code using strong.
I was assigning values to the IBOutlets before they were alloc'd/initialized. The solution I implemented was to set the values I needed to non-IBOutlet properties (NSStrings in this case) and assign those where needed, in Prompt...Controller's viewDidLoad;