I have a view with a property that should take an NSString from my view controller and display an image. If I hard code locationImageFile with "320x213-1.png" in my view, the image displays properly, but if I try to set locationImageFile from my view controller, the image doesn't appear. I feel like I'm missing something pretty basic. Side note: I seem to be able to set the locationTitle property from my view controller without any problems.
LocationViewController.m
#import "LocationViewController.h"
#import "LocationView.h"
#implementation LocationViewController
{
LocationView *_locationView;
}
- (void)loadView
{
CGRect frame = [[UIScreen mainScreen] bounds];
_locationView = [[LocationView alloc] initWithFrame:frame];
[self setView:_locationView];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
_locationView.locationTitle.text = aLocation.name;
_locationView.locationImageFile = #"320x213-1.png";
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
LocationView.m
#import "LocationView.h"
#implementation LocationView
#synthesize locationTitle;
#synthesize locationImageFile;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
[self setBackgroundColor: [UIColor blueColor]];
// Image container
UIImage *locationImage = [UIImage imageNamed:locationImageFile];
UIImageView *locationImageContainer = [[UIImageView alloc] initWithImage:locationImage];
[locationImageContainer setTranslatesAutoresizingMaskIntoConstraints:NO];
locationImageContainer.backgroundColor = [UIColor yellowColor];
[self addSubview:locationImageContainer];
// Text line
locationTitle = [[UILabel alloc]init];
[locationTitle setTranslatesAutoresizingMaskIntoConstraints:NO];
locationTitle.backgroundColor = [UIColor whiteColor];
[self addSubview:locationTitle];
}
return self;
}
#end
I think this is because the loadView method are invoke earlier than viewDidLoad method.
so when you set _locationView.locationImageFile = #"320x213-1.png";,the containerView's image are not being set.
You can consider declare locationImageContainer as a property of locationView , and set it's image directly.like
_locationView.locationImageContainer.image = [UIImage imageNamed:#"320x213-1.png"];
instead of setting locationImageFile as a property.
When LocationView is initialized, the value of the instance variable locationImageFile equals nil. Override the setter of the locationImageFile property inside LocationView.m like this:
- (void)setLocationImageFile:(NSString *)aLocationImageFile
{
locationImageFile = aLocationImageFile;
locationImageContainer.image = [UIImage imageNamed:aLocationImageFile];
}
You can try, doing it like this:
_locationView.locationImageFile = [UIImage imageNamed:locationImageFile];
if you did it like this:
_locationView.locationImageFile = locationImageFile;
Related
In my application, I do not use the NavigationController, in general.
In UITableView I would do so, would add
[Self.view addSubview: self.myCustomHeaderView];
But I'm using ASTableNode. If I do something, something similar here:
- (instancetype)init {
_tableNode = [[ASTableNode alloc] init];
self = [super initWithNode:_tableNode];
if (self) {
_tableNode.dataSource = self;
_tableNode.delegate = self;
self.navigationItem = //navigationItem implement
UINavigationBar *navbar = [[UINavigationBar alloc]initWithFrame:CGRectMake(0, 0, 320, 50)];
navbar.backgroundColor = [UIColor redColor];
navbar.items = #[self.navigationItem];
ASDisplayNode *navBarNode = [[ASDisplayNode alloc] initWithViewBlock:^UIView * _Nonnull {
return navbar;
}];
[self.node addSubnode:navBarNode];
}
return self;
}
Then this node is added as part of the list and scrolled along with the list, and I need it to be as fixed header.
initWith ASDisplayNode rather than ASTableNode,then add table node on VC's node,for example:
#interface OCTextureTableController : ASViewController<ASDisplayNode *>
#property (nonatomic, strong) ASTableNode *tableNode;
- (instancetype)init
{
self = [super initWithNode:[ASDisplayNode new]];
if (self) {
self.tableNode = [[ASTableNode alloc] init];
}
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
self.tableNode.backgroundColor = [UIColor yellowColor];
self.tableNode.frame = CGRectMake(0, NAVIGATION_BAR_HEIGHT, SCREEN_WIDTH, SCREEN_HEIGHT-NAVIGATION_BAR_HEIGHT);
[self.node addSubnode:self.tableNode];
}
(i) take Class A as base Class.
(ii) take Class B as derived Class having type of class A.
Now in class A Add a uiview on top. that will be considered as navigation.(do anything in that view)
To use same navigation bar: you have to take other all classes as having type of class A.
that's it.
I am trying to change self.navigationController.toolbar position to top instead of a bottom.
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController <UIToolbarDelegate, UIBarPositioningDelegate>
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
// View did load
- (void)viewDidLoad
{
// Superclass view did load method call
[super viewDidLoad];
// UIToolbarDelegate
self.navigationController.toolbar.delegate = self;
}
- (void)viewDidLayoutSubviews
{
self.navigationController.toolbarHidden = NO;
self.navigationController.toolbar.frame = CGRectMake(self.navigationController.toolbar.frame.origin.x, 64.0f, self.navigationController.toolbar.frame.size.width, self.navigationController.toolbar.frame.size.height);
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"First", #"Second"]];
segmentedControl.frame = CGRectMake(50.0f, 10.0f, 220.0f, 24.0f);
segmentedControl.selectedSegmentIndex = 1;
[self.navigationController.toolbar addSubview:segmentedControl];
}
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar
{
return UIBarPositionTopAttached;
}
#end
The position changes at first, but later gets back to the bottom. Please, help me!
First make sure that toolbar delegate method positionForBar: is get called. If not, then your toolbar delegate is not properly set and you've have to define the UIToolbarDelegate protocol inside your header class.
#interface ExampleViewController : UIViewController <UIToolbarDelegate>
...
#end
Then set the delegate and also change the frames for toolbar. However, for the orientation you might have to reconsider the frames of toolbar.
#implementation ExampleViewController
- (void)viewDidLoad {
[super viewDidLoad];
// set the toolbar delegate
self.navigationController.toolbar.delegate = self;
self.navigationController.toolbarHidden = NO;
// create a toolbar child items
UISegmentedControl *segmentedControl = [[UISegmentedControl alloc] initWithItems:#[#"First", #"Second"]];
segmentedControl.frame = CGRectMake(0.0f, 0.0f, self.view.frame.size.with, 24.0f);
segmentedControl.selectedSegmentIndex = 1;
[self.navigationController.toolbar addSubview:segmentedControl];
// set the frames
CGRect toolbarFrame = self.navigationController.toolbar.frame;
toolbarFrame.origin.y = self.navigationController.frame.size.height;
self.navigationController.toolbar.frame = toolbarFrame;
}
// pragma mark - UIToolbarDelegate
- (UIBarPosition)positionForBar:(id <UIBarPositioning>)bar
{
return UIBarPositionTopAttached;
}
#end
In your viewDidLoad method, add:
self.navigationController.toolbar.delegate = self;
I can't intercept the init function that's getting called when it's getting created inside of the xib file.
I want to add borderline to it when it gets created so that I won't need to add it manually.
.h:
#import <UIKit/UIKit.h>
#interface UITextView (FITAddBorderline)
- (id) init;
- (id) initWithFrame:(CGRect)frame;
#end
.m:
#import "UITextView+FITAddBorderline.h"
#implementation UITextView (FITAddBorderline)
- (id) init
{
self = [super init];
if (self) {
[self addBorderline];
}
return self;
}
- (id) initWithFrame:(CGRect)frame {
self = [super init];
if (self) {
self.frame = frame;
[self addBorderline];
}
return self;
}
- (void) addBorderline {
//To make the border look very close to a UITextField
[self.layer setBorderColor:[[[UIColor grayColor] colorWithAlphaComponent:0.5] CGColor]];
[self.layer setBorderWidth:2.0];
//The rounded corner part, where you specify your view's corner radius:
self.layer.cornerRadius = 5;
self.clipsToBounds = YES;
}
#end
Views that come from NIBs are initialized with initWithCoder:
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self)
{
[self addBorderline];
}
return self;
}
As a side note, I would recommend changing what you are doing and use a subclass instead of a category. You can get yourself into some trouble overriding methods in a category. See more info here.
You just need to implement the awakeFromNib method:
-(void)awakeFromNib
{
[super awakeFromNib];
[self addBorderline];
}
I'm trying to position a button so that it is always an X amount of pixels from the bottom of the screen. The view is laid out programmatically using auto layout. If I use: #"V:|-44-[closeModalButton]" the object aligns 44 pixels from the top of the screen as expected. However, #"V:[closeModalButton]-44-|" causes the button to never show up. It seems like it ought to be pretty straightforward, so I feel like I'm missing something really obvious.
Implementation of view
#import "DetailView.h"
#implementation DetailView
#synthesize closeModalButton;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
// Initialization code
self.backgroundColor = [UIColor whiteColor];
CGRect aFrame = [[UIScreen mainScreen] bounds];
self.frame = aFrame;
closeModalButton = [UIButton buttonWithType:UIButtonTypeCustom];
[closeModalButton setImage: [UIImage imageNamed:#"closeButton.png"] forState:UIControlStateNormal];
[closeModalButton setTranslatesAutoresizingMaskIntoConstraints:NO];
[self addSubview:closeModalButton];
NSDictionary *viewArranging = NSDictionaryOfVariableBindings(closeModalButton);
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"V:[closeModalButton(44)]-44-|"
options:0
metrics:0
views:viewArranging]];
[self addConstraints:[NSLayoutConstraint constraintsWithVisualFormat:#"H:|-149-[closeModalButton(44)]-149-|"
options:0
metrics:0
views:viewArranging]];
}
return self;
}
#end
View controller
#import "DetailViewController.h"
#interface DetailViewController ()
#end
#implementation DetailViewController
{
DetailView *_detailView;
}
- (void)loadView
{
_detailView = [[DetailView alloc] init];
[self setView:_detailView];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
[_detailView.closeModalButton addTarget:self
action:#selector(closeModalButtonPressed:)
forControlEvents:UIControlEventTouchUpInside];
}
- (void)closeModalButtonPressed:(UIButton *)sender{
[self dismissViewControllerAnimated:YES
completion:nil];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
Ok, so it looks like DetailView.h subclassed UIScrollView rather than UIView. Setting the proper subclass caused the constraints to operate as expected.
I've created a view with a variable and loaded it in the loadView method of a view controller. How do I pass a value to the view variable from the view controller after the loadView method has been called?
LocationView.m
#import "LocationView.h"
#implementation LocationView
#synthesize locationTitle;
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if (self) {
locationTitle = [[UILabel alloc]initWithFrame:CGRectMake(10, 10, 300, 20)];
[self addSubview:locationTitle];
}
return self;
}
LocationViewController.m
#import "LocationViewController.h"
#import "LocationView.h"
#interface LocationViewController ()
#end
#implementation LocationViewController
- (void)loadView
{
CGRect frame = [[UIScreen mainScreen] bounds];
LocationView *locationView = [[LocationView alloc] initWithFrame:frame];
[self setView:locationView];
}
- (void)viewDidLoad
{
[super viewDidLoad];
How do I pass a value to locationTitle here?
}
You've already set up the locationTitle property for LocationView objects, so you can just access that. The only thing you need to do beforehand is keep a reference to the LocationView object around in an instance variable so you can access it from any instance method.
#implementation LocationViewController {
LocationView *_locationView;
}
- (void)loadView
{
CGRect frame = [[UIScreen mainScreen] bounds];
_locationView = [[LocationView alloc] initWithFrame:frame];
[self setView:_locationView];
}
- (void)viewDidLoad
{
[super viewDidLoad];
_locationView.locationTitle = #"Test";
}
#end
Alternatively, since you are assigning the custom view to the view controllers main view, you could cast that:
- (void)viewDidLoad
{
[super viewDidLoad];
((LocationView *)self.view).locationTitle = #"Test";
}