The code I have is pretty much this (no custom views, just a single view application):
viewController.h:
#interface ViewController : UIViewController <UITextFieldDelegate>
...
...
#property (strong, nonatomic) IBOutlet UILabel *statusMessage;
#end
ViewController.m:
#synthesize statusMessage = _statusMessage;
- (void) viewDidLoad {
...
...
...
self.statusMessage = [[UIlabel alloc] initWithFrame:CGRectMake(...)];
[self.statusMessage setTextColor:[UIColor redColor]];
}
I am able to change the background color and I have created other labels that display properly with which ever colors I choose for them, but no matter what I do this label always displays as a grayish color. Any suggestions are appreciated!
Is your label disabled? Check the value of enabled; if it's NO, that could override your color. Ditto for highlighted; if it's YES, it will use the highlighted color.
Related
I user Interface Builder to position a UIButton and a UIImageView superimposed.
In the code, I change button label if image exists
In Example.h
#property (strong, nonatomic) IBOutlet UIButton *takePicture;
#property (strong, nonatomic) IBOutlet UIImageView *image;
In Example.m
[self.image setImage:aPhoto];
(...)
NSString *pictureButtonTitle = myCondition#"Changer la photo":#"Ajouter une photo";
(...)
[self.takePicture setTitle:pictureButtonTitle forState:UIControlStateNormal];
I use this code for a view, and I see "Change picture" correctly on my picture when myCondition is true.
But in another view, nothing appears !! WHY ?
You could either do it in the interface builder - as you did, or do it in your viewDidLoad method:
- (void)viewDidLoad {
[super viewDidLoad];
[self.view bringSubviewToFront:self.button];
}
Arranging the outlets in the IB as you did mean that the lower object will be on top of the others... The button will be "front"/on top when it is placed below all other objects as you shown in the screenshot.
If you wish to arrange the outlets differently, you could use these methods as well:
[self.view insertSubview:self.button aboveSubview:self.imageView];
Or:
[self.view insertSubview:self.imageView belowSubview:self.button];
Well, I found out : in Interface Builder, it seems that the order you place your objects matters
If you place an UIImageView before UIButton, it works well.
I see the label
But if you do the reverse : button is under the image.
And the label is not displayed
I still don't know if it's the only way to rearrange these items ?
What I would like the code to do is so when the button is pressed it runs the function in the Label.m file and it then sets the labels text to "test". Whenever I run it the code calls the function but doesn't change the labels text. Can someone please help me fix my code or show me the correct and easiest way to change a labels text from a class file.
In my FirstViewController.h
#interface FirstViewController : UIViewController{
IBOutlet UILabel *test;
}
#property (nonatomic, retain) IBOutlet UILabel *test;
In my FirstViewController.m
#import "Label.h"
-(IBAction)refresh:(id)sender {
[Label getSchedule];
}
In my Label.h
#import "FirstViewController.h"
#interface Label : NSObject
+ (void)getSchedule;
#end
In my Label.m
#import "FirstViewController.h"
#implementation Label
+ (void)getSchedule{
NSLog(#"log");
FirstViewController *VC = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
VC.test.text = #"test";
}
#end
Edit: As Maddy mentioned in the comments the original posters code would have worked if it was just called after the viewController had gotten all of its view objects. The easy way to achieve what the original poster wanted would be to simply add:
self.test.text = #"test";
to the viewControllers viewDidLoad method.
I'll leave my original answer here anyway, as I believe it improves on the original posters code and removes some of its dependencies. It still is way too complicated for what it wants to achieve but the pattern as such could be transferred to more befitting scenarios:
To elaborate on my comment:
Your method
+ (void)getSchedule{
NSLog(#"log");
FirstViewController *VC = [[FirstViewController alloc] initWithNibName:#"FirstViewController" bundle:nil];
VC.test.text = #"test";
}
Is a class method. So, naturally it is fired, but your UILabel instance test this instance have no idea about this. Furthermore you seem to have created your own class Label which subclasses NSObject, but the actual label instance is a regular UILabel.
I would guess what you are trying to do is something like this:
#interface Label : UILabel
- (void)getSchedule;
#end
...
#interface FirstViewController : UIViewController
#property (nonatomic, retain) IBOutlet Label *test;
Edit: forgot the method(!)
- (void)getSchedule{
self.text = #"test";
}
And finally in your viewController...
#import "Label.h"
-(IBAction)refresh:(id)sender {
[self.test getSchedule];
}
I have a UISlider placed in my main view and I have added a subview UIView (via interface builder) that I have associated with its own class SecondView. I need to pass the value of the slider to my sub view to move a point in the sub view when the slider changes.
I have made changes to the original code and the the below paragraph no longer is accurate. I used used the suggested changes offered by #MatthiasBauch.
I thought it would be simple a matter of sharing an iVar between the two. I created an iVar myPoint using #property (if this is still considered an iVar) in my ViewController interface, set myPoint = sliderValue.value in my ViewController implementation in the IBAction for when the slider value changes. Then in my SecondView implementation I #import "ViewController.h" then call my call my iVar in my SecondView implementation but the way I have done it it only returns nil or 0 instead of the slider value.
I don't want to use global variables.
I have looked at other post that seem to be asking a similar question but I'm still missing the concept, I guess. My code is below.
ViewController.h
#import <UIKit/UIKit.h>
#import "SecondView.h"
#interface ViewController : UIViewController
{
SecondView *secondView; // Do I need this with secondView declared as a #property below?
}
#property (nonatomic, retain) SecondView *secondView;
- (IBAction)sliderChanged:(id)sender;
#property (weak, nonatomic) IBOutlet UISlider *sliderValue;
#property (weak, nonatomic) IBOutlet UILabel *myLabel;
#property (weak, nonatomic) IBOutlet UIView *myView;
#end
ViewController.m
#import "ViewController.h"
#import "SecondView.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize sliderValue, myLabel, myView, secondView;
- (void)viewDidLoad
{
[super viewDidLoad];
secondView.thePoint = 50;
NSLog(#"%f", secondView.thePoint); // This is retuning a zero
}
- (IBAction)sliderChanged:(id)sender
{
secondView.thePoint = sliderValue.value;
myLabel.text = [NSString stringWithFormat:#"%.2f", sliderValue.value];
[secondView setNeedsDisplay];
}
#end
SecondView.h
#import <UIKit/UIKit.h>
#interface SecondView : UIView
#property (assign, nonatomic) CGFloat thePoint;
#end
SecondView.m
#import "SecondView.h"
#implementation SecondView
#synthesize thePoint;
- (void)drawRect:(CGRect)rect
{
float aPoint = thePoint;
NSLog(#"%f", aPoint); // this is retuning 0.000000
UIBezierPath *point = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(aPoint, 100, 4, 4)];
[point fill];
}
#end
Tell the view where to draw and don't ask the (newly allocated) viewController where to draw.
You are allocating a new viewController, this viewController of course does not know the value you set in the viewController where you actually changed the slider.
This won't work. Those two viewControllers are not the same instance. They share the same class, but that's it. Values from one viewController instance don't magically appear in a second instance.
Instead you should set a point property of the secondary view in your slider action.
Something like this:
Add a float #property to your view
#interface SecondView : UIView
#property (assign, nonatomic) CGFloat point;
#end
to draw use that point and not the initial value from a new ViewController instance.
- (void)drawRect:(CGRect)rect
{
float aPoint = self.point;
UIBezierPath *point = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(aPoint, 100, 4, 4)];
[point fill];
}
and set the point property of the secondary view in the slider action
- (IBAction)sliderChanged:(id)sender
{
secondView.point = sliderValue.value;
[secondView setNeedsDisplay]; // you might be able to omit that
myLabel.text = [NSString stringWithFormat:#"%.2f", myPoint];
}
Your ViewController has a property called #myView which points to the instance of SecondView created by the runtime.
So, your ViewController's implementation could call the drawRect: method on myView and pass in the relevant coordinates.
Here's some pseudo code for your ViewController.
- (IBAction)sliderChanged:(id)sender
{
myPoint = sliderValue.value;
myLabel.text = [NSString stringWithFormat:#"%.2f", myPoint];
[myView drawRect:CGRectMake(myPoint, 100, 4, 4)];
}
Note however that in your ViewController, myView is just a UIView, not a SecondView. You have a few choices on how to resolve this. The cleanest way is probably to remove the #import ViewController.h from SecondView and instead do the opposite. That is, have ViewController do an #import SecondView.h, then promote myView to a SecondView.
If that doesn't work for some reason (for example, if XCode demands that it remain strictly a UIView), you can still upcast the myView property at runtime like this:
[(*SecondView)myView drawRect:CGRectMake(myPoint, 100, 4, 4)];
Alternatively, you could point your slider's action at myView like the answer to this question does for a button: subclass UIView actions in viewcontroller
As usual in programming, there are several possible solutions. It's up to you to pick the best one for you. Good luck!
I'm having a hard time implementing a simple scroll on my detail view.
The app is straightforward with a Master and Detail views.
When the user taps an item on Master, the Detail view is pushed with larger photo, blog text and etc.
I would like the entire Detail view to scroll, so if the picture is tall, or the text is long, they can scroll vertically to see/read more. I do not want the user to scroll these items individually. It should feel like webpage scrolling.
Currently my Detail view loads OK but I can't make it scroll.
My DetailViewController.h
#import <UIKit/UIKit.h>
#interface DetailViewController : UIViewController {
IBOutlet UILabel *postTextLabel; // wired to Text Label
IBOutlet UILabel *postAuthorNameLabel; // wired to Author Label
}
#property (strong, nonatomic) id detailItem;
#end
My DetailViewController.m
#import "DetailViewController.h"
#interface DetailViewController ()
- (void)configureView;
#end
#implementation DetailViewController
- (void)viewDidLoad
{
[super viewDidLoad];
[self configureView];
}
- (void)configureView
{
if (self.detailItem) {
NSDictionary *post = self.detailItem;
NSString *postText = [post objectForKey:#"post_text"];
NSString *postAuthorName = [post objectForKey:#"post_author_name"];
postTextLabel.text = postText;
postAuthorNameLabel.text = postAuthorName;
}
}
#end
Structure on IB:
Any ideas on what's missing to make this work?
I would do the following:
1)(optional)turn your View into a scrollview by dragging it into the view in the scruture list on the side.
2)link the scrollView into your viewcontroller .h and make an Outlet connection something like this
#property (strong, nonatomic) IBOutlet UIScrollView *scroller;
(make sure you add #synthesize in the .m if you add this manually)
and make sure it is connected in IB!
3)set the contentsize of the scrollview in viewDidLoad method
scroller.contentSize = CGSizeMake(320,550);
NOTE: IBOutlet UILabel *postTextLabel; should actually probably be a UITextView so you can access ContentSize
Which would allow for the following.
CGRect frame = postTextLabel.frame;
frame.size = postTextLabel.contentSize;
postTextLabel.frame = frame;
scroller.contentSize = CGSizeMake(320, frame.size.height+200);//200 or how ever much space is above the textView
and again that only works if you use a UITextView
for ipad replace 320 with 768 or 1024, or whichever depending on orientation
The best way to connect it in IB is like this holding down control and dragging to the .h file
and make sure it is set to automatic like in the picture, and pointing to> the .h of your view.
Adding it like this also automatically adds the #synthesize for you.
Make sure UserInteractionsEnabled are checked here for our scrollview
I've got a subclass of UITableViewCell. My subclass contains several UILabels. I want my subclass to initialize these labels to some default settings that applies to every table view cell of mine.
I read that I should be using initWithCoder for this. My initWithCoder function is being called, and I can step through each line in my function and it appears to go through the motions. When I run my application I do not see any of the properties being applied, though. Most noticeably, the font is not being changed. I just don't think any of the properties that I'm modifying on my UILabels are actually being saved, or displayed.
I'm using this subclass in conjunction with a Storyboard. I know my changes will not be reflected on the Storyboard, but they're also not being reflected when the application runs - despite my code being executed.
Edit: I wanted to mention that prior to trying to override initWithCoder, I had an instance method in these subclasses that I'd run this logic in. I would just call that instance method inside of cellForRowAtIndexPath. This method was working, but I thought it'd be handy to have this logic in this subclass occur automatically.
Any ideas? My code is below:
#import "ThreadListCell.h"
#implementation ThreadListCell
- (id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
// adjust the font settings of the title
self.title.font = [UIFont fontWithName:#"SourceSansPro-Black" size:16];
self.title.textColor = [UIColor colorWithWhite:0.267f alpha:1.0f];
// adjust the font settings of the subtitle
self.text.font = [UIFont fontWithName:#"SourceSansPro-Light" size:14];
self.text.textColor = [UIColor colorWithWhite:0.267f alpha:0.9f];
self.text.textColor = [UIColor colorWithRed:1 green:0 blue:0 alpha:1];
// adjust the font settings of the location
self.location.font = [UIFont fontWithName:#"SourceSansPro-Light" size:8];
self.location.textColor = [UIColor colorWithWhite:0.267f alpha:0.9f];
// adjust the UILabel settings of the title
self.title.numberOfLines = 0;
self.title.lineBreakMode = UILineBreakModeTailTruncation;
// adjust the UILabel settings of the subtitle
self.text.numberOfLines = 0;
self.text.lineBreakMode = UILineBreakModeTailTruncation;
// adjust the UILabel settings of the location
self.location.numberOfLines = 0;
self.location.lineBreakMode = UILineBreakModeTailTruncation;
self.location.textAlignment = UITextAlignmentRight;
}
return self;
}
#end
And the header:
#import <UIKit/UIKit.h>
#interface ThreadListCell : UITableViewCell
#property (nonatomic, weak) IBOutlet UILabel *text;
#property (nonatomic, weak) IBOutlet UILabel *title;
#property (nonatomic, weak) IBOutlet UILabel *location;
#end
None of your IBOutlets is set when you get the message - you need to use "awakeFromNib" or "viewDidLoad" - something like that - to access your outlets. That said, you can set other non-outlet stuff in the initWithCoder.