ViewController is not updating UIView with custom class - ios

I'm not sure if I have my view controller in my storyboard file connected to my view correctly but here's a breakdown of the setup - I'm using xcode 5:
One view controller using custom class CICBoostGaugeViewController (configured in identity inspector).
One view using custom class CICGaugeBuilder (configured in identity inspector in storyboard file).
The CICGaugeBuilder class draws a gauge and sets the properties of the gauge in an init method. When I run this setup in the simulator the gauge appears correctly based on the initialized gauge parameters in CICGaugeBuilder. No problems so far.
My issue is when I create an instance of the CICGaugeBuilder class in my view controller and set the properties, they do not show up when I run it in the sim, only the values initialized in the CICGaugeBuilder class are applied.
CICBoostGaugeViewController.h
#import <UIKit/UIKit.h>
#import "CICGaugeBuilder.h"
#class CICGaugeBuilder;
#interface CICBoostGaugeViewController : UIViewController{
CICGaugeBuilder *boostGauge;
}
#property (nonatomic, retain) IBOutlet CICGaugeBuilder *boostGauge;
#end
CICBoostGaugeViewController.m
#import "CICBoostGaugeViewController.h"
#import "CICGaugeBuilder.h"
#interface CICBoostGaugeViewController ()
#end
#implementation CICBoostGaugeViewController
#synthesize boostGauge;
- (void)viewDidLoad
{
[super viewDidLoad];
self.boostGauge.minGaugeNumber = 0;
self.boostGauge.maxGaugeNumber = 25;
self.boostGauge.gaugeLabel = #"Boost/Vac";
self.boostGauge.incrementPerLargeTick = 10;
self.boostGauge.tickStartAngleDegrees = 135;
self.boostGauge.tickDistance = 270;
self.boostGauge.menuItemsFont = [UIFont fontWithName:#"Helvetica" size:14];
self.boostGauge.value = 10;
}
- (void)viewDidUnload
{
//self.boostGauge = nil;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
This is the initialization method in the CICGaugeBuilder class:
self.minGaugeNumber = 0;
self.maxGaugeNumber = 100;
self.gaugeType = 2;
self.gaugeLabel = #"Boost/Vac";
self.incrementPerLargeTick = 10;
self.tickStartAngleDegrees = 135;
self.tickDistance = 270;
self.menuItemsFont = [UIFont fontWithName:#"Helvetica" size:14];
Note that the maxGaugeNumber of 100 is retained when run in the simulator. The gauge draws correctly, but the problem is the object instance in the view controller is not used. I've tried [self.boostGauge SetNeedsDisplay] and it did not work.
In my storyboard file the view controller does not have any referencing outlets. I think this needs to be connected to the app delegate but I'm not sure. Dragging the view controller to the app delegate does not allow a connection to be made.
Here is the CICAppDelegate.h file:
#import <UIKit/UIKit.h>
#class CICBoostGaugeViewController;
#interface CICAppDelegate : UIResponder <UIApplicationDelegate>{
UIWindow *window;
CICBoostGaugeViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet CICBoostGaugeViewController *viewController;
#end

As I go through you App,I found.
After calling [self.boostGauge SetNeedsDisplay] will not make any kind of effect because:
SetNeedsDisplay calls the - (void)drawRect:(CGRect)rect method of CICGaugeBuilder Class
and
- (void)drawRect:(CGRect)rect
{
CGRect innerFrame;
// self.value = 0;
[self initializeGauge];
}
here you again calling initialize method and initialise method will again set value to initial value.
ULTIMATELY NO EFFECT.
Most importantly you call value using
CICAppDelegate *ap=(CICAppDelegate *)[[UIApplication sharedApplication]delegate];
ap.guage.value=50;
Take a object reference of CICGaugeBuilder Class in appDel.
Add following to initialiseGuageMethod
CICAppDelegate *ap=(CICAppDelegate *)[[UIApplication sharedApplication]delegate];
ap.guage=self;

Related

Why does subclassing the main ViewController's view causes delegates to never fire?

I made a customView that implements its own delegate and set it up inside the main viewController. It works perfectly well, it's the standard practice, there's no need to show any code.
For the sake of better organizing the code I created a manager called customManager that contains the customView and the main viewController's view.
Instead of having all the code that it's needed inside the viewController (managing how the customView is setup and also listening to its delegate) I moved all that code to the customManager instead. That's why I made the customManager just to clear up the code that's inside the viewController.
All renders properly but the delegate never fires.
CustomManager.h
#import "CustomView.h"
#interface CustomManager : NSObject <CustomViewDelegate>
#property (weak) UIView *view; // viewController's view
#property (strong) CustomView *customView;
- (void)load;
#end
CustomManager.m
#import "CustomManager.h"
#implementation CustomManager
// Initialization Method
- (void)load {
_customView = [[CustomView alloc] init];
_customView.delegate = self; // !!!
_customView.frame = CGRectMake(0.0, 20.0, _view.frame.size.width, _view.frame.size.height - 20.0);
[_view addSubview:_customView];
}
#pragma mark - CustomViewDelegate
// Delegate Methods
#end
ViewController.h
#import "CustomManager.h"
#interface ViewController : UIViewController
#property (strong) CustomManager *customManager;
#end
ViewController.m
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_customManager = [[CustomManager alloc] init];
_customManager.view = self.view;
[_customManager load];
// 1. The load method above removes the code needed here for initializing the customView and setting it up correctly.
// 2. The delegate methods are now in the customManager and leave the space below clear.
}
#end

exc_bad_access code=1 when loading UIView

I have an app where I need to present an overlay for feedback. I started by simply creating the exact thing I wanted within the UIViewController I wanted. However this presents to 2 problems. 1) I can't reuse this in another view (As I need to now) and 2) Because it's an overlay, it covers the entire UIViewController on the storyboard so I can't see the controls beneath it.
I looked at moving to an external UIView .xib file and loading dynamically which worked great, except whatever I did, I couldn't never get a handle on the labels within the nib to update the text.
Then I decided that making it a class and creating a delegate method for it would probably be the best way forward.
I have created a very simply .xib and laid it out as well as a .h and .m file (overlayView) and wired it all in an it looks good, except when trying to present the overlayView I get a exc_bad_access on the line
[window addSubview:self];
And I can't work out why. Full code below:
overlayView.h
#import <UIKit/UIKit.h>
#class overlayView;
#protocol overlayDelegate;
#interface overlayView : UIView
#property (nonatomic, strong) id <overlayDelegate> delagate;
-(instancetype)initWithTitle:(NSString *)title
dateFrom:(NSString *)dateFrom
dateTo:(NSString *)dateTo
description:(NSString *)description;
#property (strong, nonatomic) IBOutlet UILabel *overlayTitleLbl;
#property (strong, nonatomic) IBOutlet UILabel *overlayDateFromLbl;
#property (strong, nonatomic) IBOutlet UILabel *overlayDateToLbl;
#property (strong, nonatomic) IBOutlet UILabel *overlayDescLbl;
#property (strong, nonatomic) IBOutlet UILabel *overlayIcon;
-(void)showOverlay;
-(void)dismissOverlay;
#end
#protocol overlayDelegate <NSObject>
#optional
#end
overlayView.m
#import "overlayView.h"
#import "NSString+FontAwesome.h"
#implementation overlayView
- (instancetype)initWithTitle:(NSString *)title dateFrom:(NSString *)dateFrom dateTo:(NSString *)dateTo description:(NSString *)description {
self.overlayViewTitleLbl.text = title;
self.overlayViewDateFromLbl.text = dateFrom;
self.overlayViewDateToLbl.text = dateTo;
self.overlayViewDescLbl.text = description;
self.overlayViewIcon.text = [NSString fontAwesomeIconStringForIconIdentifier:#"fa-calendar"];
return self;
}
-(void)showOverlay {
UIWindow *window = [[UIApplication sharedApplication] keyWindow];
[window addSubview:self]; <-- Code causing issue
[window makeKeyAndVisible];
}
-(void)dismissOverlay {
// Not wired in yet
}
#end
The being called in my main view controller like:
overlay = [[overlayView alloc] initWithTitle:[tmpDict objectForKeyedSubscript:#"Title"] dateFrom:startDate dateTo:stopDate description:[tmpDict objectForKeyedSubscript:#"Desc"]];
[overlay showOverlay];
Any ideas why this doesn't want to play ball? I have breakpointed the initWithTitle method and all information is being passed correctly so I think I am very close to what I am trying to achieve.
you need to initiate your view first, you're returning self without initiating it
- (instancetype)initWithTitle:(NSString *)title dateFrom:(NSString *)dateFrom dateTo:(NSString *)dateTo description:(NSString *)description {
self = [super init];
if (self) {
self.overlayViewTitleLbl.text = title;
self.overlayViewDateFromLbl.text = dateFrom;
self.overlayViewDateToLbl.text = dateTo;
self.overlayViewDescLbl.text = description;
self.overlayViewIcon.text = [NSString fontAwesomeIconStringForIconIdentifier:#"fa-calendar"];
}
return self;
}

How to change variable of custom UIView from ViewController

I have created a custom UIView (ProgressView) where I draw a shape imported via StyleKit from PaintCode.
Below are the codes. I have declared instance variable property in my custom UIView and when I try to change property from ViewController, It does not work.
ProgressView.h
#import <UIKit/UIKit.h>
#interface ProogressView : UIView
#property (nonatomic) float daysFraction;
#property (nonatomic) float pagesFraction;
#end
ProgressView.m
#import "ProgressView.h"
#import "StyleKitName.h"
#import "ViewController.h"
#implementation ProgressView
#synthesize daysFraction = _daysFraction;
#synthesize pagesFraction = _pagesFraction;
- (void)drawRect:(CGRect)rect {
// Drawing code
[StyleKitName drawCanvas1WithDaysFraction:self.daysFraction pageFraction:self.pagesFraction];
}
-(void)awakeFromNib {
[super awakeFromNib];
self.pagesFraction = 0;
self.daysFraction = 0;
}
ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
#end
*ViewController.m**
#import "ViewController.h"
#import "ButtonAnimation.h"
#import "ProgressView.h"
#import "StyleKitName.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet ButtonAnimation *buttonView;
#property (weak, nonatomic) IBOutlet UIButton *actionButton;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
ProgressView *new =[[ ProgressView alloc]init];
new.daysFraction = 0.7f; // here I am setting value to variable in custom view ProgressView but not working.
}
- (IBAction)animateTheButton:(id)sender {
self.buttonView.layer.backgroundColor = [UIColor clearColor].CGColor;
[self.buttonView addErrorAnimation];
}
#end
You need to add this view to UIViewController's view:
[self.view addSubview:progressView];
Later, you must also set a frame. Eg
[progressView setFrame:self.view.bounds];
You may do it in viewDid/WillLayoutSubviews method to change it on rotation / window resize event.
BTW, do not name your view as new, it's horrible. Such name doesn't even tell what kind of variable is it.

Application windows are expected to have a root view controller at the end of application

I have one problem and I've read following solution.This is my code
AppDelegat.h
#import <UIKit/UIKit.h>
#class ViewController;
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property(strong,nonatomic)ViewController *vobj;
#end
AppDelegate.m
#import "AppDelegate.h"
#import "ViewController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window= [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
self.vobj = [[ViewController alloc]initWithNibName:#"ViewController" bundle:nil];
self.window.rootViewController = self.vobj;
// Override point for customization after application launch.
self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
}
and it gives an error Application windows are expected to have a root view controller at the end of application launch
This is my code
https://www.dropbox.com/s/y3gzur3tb032nz3/slide.zip
Applications are expected to have a root view controller at the end of application launch
Application windows are expected to have a root view controller at the end of application launch warning
Application windows are expected to have a root view controller at the end of application launch - even with all known issues fixed
and other link...
Thank You.
I found the source of the problem, and I made it work. It is deeper than it seems. The general problem is that on your "synthesised" line, you have also set the 'view' outlet to be synthesised. The 'view' is automatically associated on view creation with the 'view' property inside a view controller by iOS, and you just did an override on that association.
Change your line to this
#synthesize slide1,slide2,slide3,segmentview,segment1,segment2,switch1,newslider,lbl;
and you will be fine. The problem was that although your view controller was instantiated and assigned as a root view controller, its 'view' property was set to nil. You could see that using the debugger. iOS probably interpreted the nil view as an unassigned root view controller, hence the error you were seeing.
On a side note, might I give you some advice on how to save time, redundancy and make your code cleaner? Consider the following code:
#interface ViewController : UIViewController
{
// UISlider *slide1;
// UISlider *slide2;
// UISlider *slide3;
// UIView *newslider;
// UIView *segment1;
// UIView *segment2;
// UISegmentedControl *segmentview;
// UILabel *lbl;
// UISwitch *switch1;
//
}
#property (strong,nonatomic)IBOutlet UISlider *slide1;
#property (strong,nonatomic)IBOutlet UISlider *slide2;
#property (strong,nonatomic)IBOutlet UISlider *slide3;
#property (strong,nonatomic)IBOutlet UIView *newslider;
#property (strong,nonatomic)IBOutlet UIView *segment1;
#property (strong,nonatomic)IBOutlet UIView *segment2;
#property (strong,nonatomic)IBOutlet UISegmentedControl *segmentview;
#property (strong,nonatomic)IBOutlet UILabel *lbl;
#property (strong,nonatomic)IBOutlet UISwitch *switch1;
-(IBAction)btnchangecolor:(id)sender;
#end
Then, your view controller implementation would be like this:
#implementation ViewController
//#synthesize slide1,slide2,slide3,segmentview,segment1,segment2,switch1,view,newslider,lbl;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
-(void)loadView {
[super loadView];
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
-(IBAction)btnchangecolor:(id)sender
{
if (_segmentview.selectedSegmentIndex==0) {
_segment1.backgroundColor=[UIColor colorWithRed:_slide1.value/255 green:_slide2.value/255 blue:_slide3.value/255 alpha:1.0];
}
else
{
_segment2.backgroundColor=[UIColor colorWithRed:_slide1.value/255 green:_slide2.value/255 blue:_slide3.value/255 alpha:1.0];
}
_lbl.backgroundColor=[UIColor colorWithRed:_slide1.value/255 green:_slide2.value/255 blue:_slide3.value/255 alpha:1.0];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
When you create a #property, modern Xcode versions produce a #property with that name, and sets the internal variable of a property like "myVar" automatically to "_myVar". Before automatic synthesizing feature, you could set the name of the internal variable by writing "#synthesize myVar = _myInternalVar", which would allow you to write "_myInternalVar = newValue" or "self.myVar = newValue" (you can still do that, by the way, if you wish). Seeing your code however, there seems to be some redundancy. You create iVars, and then, you create IBOutlets and then you synthesise the outlets with the name of the iVars. It's not an error, it's not even a warning, but you could save so much time by writing only the "#property" elements and not anything else, that I though I might just throw it as an option :)

Variable not passed to UIView

I am trying to pass a variable from within my main UIViewController to a UIView.
CGRect frame = CGRectMake(0,0,347, 308);
XBMCPopUpView * xbmcpop = [[XBMCPopUpView alloc]initWithFrame:frame];
xbmcpop.DevIP = #"2222";
[self.view addSubview:xbmcpop];
the Object xbmcpop gets created and its string property "DevIP" gets assigned correctly. But when the UIVIEW is actually viewed it seems like the instance that is viewed is different from the one I created and the variable #"2222" is not passed to the string property "DevIP"
Note: My Main UIViewController is in a storyboard with a navigation controller
If you are interested to see the "XBMCPopUpView class, here it is:
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#class XBMCPopUpView;
#interface XBMCPopUpView : UIView
{
NSString * DevIP;
}
#property (strong,nonatomic) NSString *DevIP;
- (id)initWithFrame:(CGRect)frame;
-(IBAction)sendPlay:(id)sender;
#end
Under
#interface XBMCPopUpView : UIView
remove
{
NSString * DevIP;
}
Since you're using a storyboard, you need to use your view controller's awakeFromNib method for this.
When you add the awakeFromNib method, don't forget to call [super awakeFromNib] there.
- (void)awakeFromNib
{
[super awakeFromNib];
CGRect frame = CGRectMake(0,0,347, 308);
XBMCPopUpView * xbmcpop = [[XBMCPopUpView alloc]initWithFrame:frame];
xbmcpop.DevIP = #"2222";
[self.view addSubview:xbmcpop];
}

Resources