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.
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 have a custom class A that is a subclass of UIView which essentially manages a UIScrollView that fits the size of the view and the contains an UIImageView that fills that scrollView.
I am having trouble setting the imageView.image of the custom class:
Here's the class
#import "BackgroundPickerView.h"
#implementation BackgroundPickerView
#synthesize scrollView;
#synthesize imageView;
#synthesize actionButton;
-(id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
return self;
}
-(void)layoutSubviews
{
[super layoutSubviews];
//[[NSNotificationCenter defaultCenter] addObserver:self
// selector:#selector(changeImage)
// name:#"ImageChangeNotification"
// object:nil];
//Here's where we add custom subviews
scrollView = [[UIScrollView alloc] init];
imageView = [[UIImageView alloc] init];
actionButton = [[UIButton alloc] init];
[scrollView setFrame:CGRectMake(0, 0, 321, 115)];
[imageView setFrame:CGRectMake(0, 0, 321, 115)];
[actionButton setFrame:CGRectMake(0, 0, 320, 115)];
scrollView.scrollEnabled = YES;
scrollView.minimumZoomScale = 1.0;
scrollView.maximumZoomScale = 6.0;
scrollView.contentSize = CGSizeMake(300, 200);//imageView.image.size;
[scrollView addSubview:imageView];
[self addSubview:scrollView];
}
-(void)storeImage:(UIImage *)image
{
self.imageView.image = image;
}
-(void)changeImage
{
[self.imageView setImage:[UIImage imageNamed:#"random.png"]];
}
From my other class B where I receive the image I have tried using NSNotification and a simple setter method to try setting the imageView property of the class object, but cannot seem to set the imageView.image. I have tried using
instance.imageView.image = myImageToSet
//Setter
[instance storeImage:myImageToSet];
in class B but am having no success
first of all, the initialisation of subviews in layoutSubviews not the best way, better u initialise them in the init method, because layoutSubviews may call multiple times to layout the subviews, if u place the initialisation code in the layoutSubviews there might be may subviews. in layoutSubviews u only set the frame of the subviews.
and u can do like below,
#import "BackgroundPickerView.h"
#implementation CustomViewA
//Edit change below
- (id)initWithFrame:(CGRect)frame
{
self = [super initWithFrame:frame];
if(self)
{
[self commonInit];
}
return self;
}
- (void)awakeFromNib
{
[self commonInit];
}
- (void)commonInit
{
_scrollView = [[UIScrollView alloc] init];
_imageView = [[UIImageView alloc] init];
_actionButton = [[UIButton alloc] init];
_scrollView.scrollEnabled = YES;
_scrollView.minimumZoomScale = 1.0;
_scrollView.maximumZoomScale = 6.0;
[_scrollView addSubview:_imageView];
[self addSubview:_scrollView];
}
- (void)layoutSubviews
{
[super layoutSubviews];
[_scrollView setFrame:CGRectMake(0, 0, 321, 115)];
[_imageView setFrame:CGRectMake(0, 0, 321, 115)];
[_actionButton setFrame:CGRectMake(0, 0, 320, 115)];
_scrollView.contentSize = CGSizeMake(300, 200);
}
-(void)storeImage:(UIImage *)image
{
self.imageView.image = image;
}
-(void)changeImage
{
[self.imageView setImage:[UIImage imageNamed:#"random.png"]];
}
synthesise is optional
and in BackgroundPickerView.h file it is something like below
#interface BackgroundPickerView : UIView
#property (nonatomic, strong) UIScrollView *scrollView;
#property (nonatomic, strong) UIImageView *imageView;
#property (nonatomic, strong) UIButton *actionButton;
-(void)storeImage:(UIImage *)image;
-(void)changeImage;
for image u check it it should work, check the image is present or not,
Edit
For the image, in controller for example,
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
_viewA = [[BackgroundPickerView alloc] initWithFrame:self.view.bounds];
[self.view addSubview:_viewA];
}
//for testing
- (void)viewDidAppear:(BOOL)animated
{
[super viewDidAppear:animated];
[_viewA storeImage:[UIImage imageNamed:#"6.png"]]; //hear do this
}
I need a little help about my code. I want to create a custom bar graph. I did all the coding. When I create the objects in my custom class view it works like a charm. However, I want to make it generic. I would like to create it in ViewController. I also add a view in storyboard and change the class name to my custom class name.
It doesn't work when I try like this.
#implementation ViewController
-(void)viewDidLoad {
[super viewDidLoad];
GCBarGraphRow *first = [[GCBarGraphRow alloc]init];
first.backgroundColor = [UIColor redColor];
first.value = 20;
GCBarGraphRow *second = [[GCBarGraphRow alloc]init];
second.backgroundColor = [UIColor brownColor];
second.value = 40;
GCBarGraphColumn *container = [[GCBarGraphColumn alloc]init];
container.values = #[first,second];
NSLog(#"View Controller %#",container.values);
self.myGraph.array = container;
}
But when I try to create it in my custom view class it works.
#implementation GCBarGraphView
-(id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
barNumber = [array.values count];
//NSLog(#"%#",array.values);
showDifference = NO;
showShadow = NO;
gradientColor = NO;
drawBaseLine = YES;
[self baseClassInit];
}
return self;
}
-(void)baseClassInit {
GCBarGraphRow *first = [[GCBarGraphRow alloc]init];
first.backgroundColor = [UIColor redColor];
first.value = 20;
GCBarGraphRow *second = [[GCBarGraphRow alloc]init];
second.backgroundColor = [UIColor brownColor];
second.value = 40;
GCBarGraphColumn *container = [[GCBarGraphColumn alloc]init];
container.values = #[first,second];
}
If you're creating a view in the storyboard and assign it's class to your CGBarGraphRow, you also need to create an outlet to your view controller.
Then you don't have to initialize it manually from the view controller code. Your constructor initWithCoder will be called automatically.
Update:
Try this. In the storyboard create the following:
- UIView with proper frame and assign custom class to CGBarGraphView
- Insert into that view two more and assign their classes to GCBarGraphRow
In your CGBarGraphView class create two outlets and bind them to the proper views in the storyboard:
#property (nonatomic, weak) IBOutlet GCBarGraphRow *row1;
#property (nonatomic, weak) IBOutlet GCBarGraphRow *row2;
Remove the code you have above for the view controller - it's not needed. Leave something like that in the CGBarGraphView code:
-(id)initWithCoder:(NSCoder *)aDecoder {
if ((self = [super initWithCoder:aDecoder])) {
}
return self;
}
-(void)viewDidLoad {
GCBarGraphColumn *container = [[GCBarGraphColumn alloc]init];
container.values = #[self.row1,self.row2];
... whatever else you need to initialize
}
I have next issue:
this code worked well:
//UITableViewController class
- (void)viewDidLoad
{
[super viewDidLoad];
UIView *v = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 80)];
[v setBackgroundColor:[UIColor redColor]];
self.tableView.tableHeaderView = v;
}
Result:
But next code is not worked:
// TopViewController class
#interface TopViewController : UIViewController
#end
// UITableViewController class
#property (strong) TopViewController *topBar;
#synthesize topBar;
- (void)viewDidLoad
{
[super viewDidLoad];
topBar = [[TopViewController alloc] init];
topBar.view.frame = CGRectMake(0, 50, 320, 80);
[topBar.view setBackgroundColor:[UIColor greenColor]];
self.tableView.tableHeaderView = topBar.view;
}
Result - just white space
But when i do this:
topBar.view.frame = CGRectMake(0, 50, 320, 400); // change height to 400
I've got next result:
Can some one explain this strange behavior?
I want to add my custom UIView to my main view.
I want to use the function initWithTitle:description: like:
AchievementView *achievement = [[AchievementView alloc] initWithTitle:#"Test" description:#"The Descr"]];
But this doesn't work. tThe initWithTitle:description: function have to be implemented as class method.
AchievementView.h
#interface AchievementView : UIView
#property (strong) NSString *achievementTtl;
#property (strong) NSString *achievementDescr;
#property (strong) UIView *theAchievementView;
- (void)initWithTitle:(NSString*)achievementTitle description:(NSString*)achievementDescription;
- (void)showAchievement;
#end
AchievementView.m
-(void)initWithTitle:(NSString*)achievementTitle description:(NSString*)achievementDescription {
self.achievementTtl = achievementTitle;
self.achievementDescr = achievementDescription;
}
- (void)showAchievement {
// Create view popup
self.theAchievementView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 300, 423)];
self.theAchievementView.layer.cornerRadius = 8;
self.theAchievementView.layer.masksToBounds = YES;
self.theAchievementView.layer.shadowRadius = 5;
self.theAchievementView.layer.shadowOpacity = .15;
[self.theAchievementView setBackgroundColor:[UIColor whiteColor]];
[self addSubview:self.theAchievementView];
}
Call the method in main view:
- (IBAction)share:(id)sender {
AchievementView *achievement = [[AchievementView alloc] init];
achievement.achievementTtl = #"Test";
achievement.achievementDescr = #"TestDEscr";
[achievement showAchievement];
}
I can't add the subview to the main view with this function.
I think the "self" is wrong. What should be there?
[self addSubview:self.theAchievementView];
You have 2 questions: how to initialize the view and how to add it to the screen.
You can use the initWithTitle:description: method, you just have to use it on an instance of the class, not the class itself:
[[AchievementView alloc] initWithTitle:#"Test" description:#"The Descr"]];
You are correct that you have the wrong self in your addSubview call. You need a reference to the parent view. You could pass it into your AchievementView class, but it is cleaner to manage that outside of the class.
I also noticed that AchievementView is a subclass of UIView, but you are creating another UIView inside it. It would be simpler to directly use the AchievementView. Your code should be similar to the below:
AchievementView.h
#interface AchievementView : UIView
#property (strong) NSString *achievementTtl;
#property (strong) NSString *achievementDescr;
- (id)initWithTitle:(NSString*)achievementTitle description:(NSString*)achievementDescription;
#end
AchievementView.m
- (id)initWithTitle:(NSString*)achievementTitle description:(NSString*)achievementDescription {
if (self = [super initWithFrame:CGRectMake(0, 0, 300, 423)]) {
self.achievementTtl = achievementTitle;
self.achievementDescr = achievementDescription;
self.layer.cornerRadius = 8;
self.layer.masksToBounds = YES;
self.layer.shadowRadius = 5;
self.layer.shadowOpacity = .15;
self.backgroundColor = [UIColor whiteColor];
}
return self;
}
Main view
- (IBAction)share:(id)sender {
AchievementView *achievement = [[AchievementView alloc] initWithTitle:#"Test" description:#"TestDEscr"];
[self.view addSubview:achievement];
}
Number one, you are never adding achievement as a subview of your main view. Basically you are creating a view offscreen, adding a view to that view, then moving on with whatever you want to do without ever moving the first view onto the screen.
As a minimum you should do this:
- (IBAction)share:(id)sender {
AchievementView *achievement = [[AchievementView alloc] init];
achievement.achievementTtl = #"Test";
achievement.achievementDescr = #"TestDEscr";
[achievement showAchievement];
[self addSubview:achievement];
}
Along with setting the frame size of achievement which is currently never set (and since most views by default mask to their layer bounds it will mask to (0,0,0,0)).
Then I would seriously reconsider how you are dealing with views and subviews. If you do things properly, your initwithtitle will work just fine.