How to set/get UIImageView.image through Singleton? - objective-c

I have two ViewControllers.
FirstViewController has UILabels and UIImageViews. Also generated a Singleton from its class.
SecondViewController has a call of that Singleton and should GET values of UILabels and UIImageViews from FirstViewController.
NSString works, UILabel do not.
For example, access a NSString in SecondviewController with "sharedFirstViewController.nsstringvarname" I can GET and SET the value.
This works fine!
Trying the same with an UILabel like this: "sharedFirstViewController.uilabelvar.text" I doens´t can SET or GET the value of this UILable.
This works NOT!
Is there any special thing with UI-Objects?
Would be great if someone can help me with that.
Thanks!
EDIT:
in FirstViewController.h
+ (id)sharedFirstViewController;
#property (copy, nonatomic) NSString *path;
#property (strong, nonatomic) IBOutlet UIImageView *pic;
in FirstViewController.m
#synthesize path= _path;
#synthesize pic = _pic;
- (id)init {
if (self = [super init]) {
_pic = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 200)];
}
return self;
}
+ (id) sharedFirstViewController {
static sharedFirstViewController * sharedFirstViewController = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedFirstViewController = [[self alloc] init];
});
return sharedFirstViewController;
}
in SecondViewController.m
#import "FirstViewController.h"
- (void)viewDidLoad
{
FirstViewController * sharedFirstViewController = [FirstViewController sharedFirstViewController];
NSLog(#"this is NSString from FVC: %#" sharedFirstViewController.path); //works
UIImage * picture = [UIImage imageWithContentsOfFile:sharedFirstViewController.path];
sharedFirstViewController.pic.image = picture; // does´t work
}

I'm sure you forget to give allocation to UIImageview *pic in init method of singleton class. That because your code running but without any crash and warning. If you debug your code you will get imageview memory allocation 0X0. check it.
- (id)init {
if (self = [super init]) {
_pic = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 100, 200)];
}
return self;
}
write above method in in FirstViewController.m class. Their is doesn't need of write IBOutlet in front of UIImageView *pic because you not mention your viewcontroller nib while generation singleton instance. Use IBOutlet whenever you dealing UI in xib.

Related

pass array from NSViewController to NSView in Objective C Cocoa

Im making a program to draw the chart (which i keep in NSView class). However action & data I want to pass from NSViewController. So could you help me how to do it. I did try as bellow code however it doesn't work.
#implementation PlottingChart
#synthesize plotChartData;
- (void)drawRect:(NSRect)dirtyRect{
[super drawRect:dirtyRect];
[self drawChartGrid:plotChartData];
}
-(void)drawChartGrid:(NSMutableArray *)ChartData
{
//Drawing code here
}
#interface PlottingChart : NSView
#property (nonatomic, strong) NSMutableArray *plotChartData;
-(void)drawChartGrid:(NSMutableArray *)ChartData;
#end
#import "PlottingChart.h"
#interface ViewController :NSViewController<NSTableViewDataSource,NSTableViewDelegate>
{
PlottingChart *boxPlotChart;
}
- (IBAction)btnStart:(id)sender {
//trial draw chart
NSDictionary *dict1 = #{#"plot_Q1":#"180",#"plot_Q3": #"220", #"plot_Max":#"250", #"plot_Min":#"150", #"plot_Median":#"200"};
NSDictionary *dict2 = #{#"plot_Q1":#"190",#"plot_Q3": #"230", #"plot_Max":#"280", #"plot_Min":#"160", #"plot_Median":#"210"};
NSMutableArray *array = [NSMutableArray arrayWithObjects:dict1,dict2, nil];
boxPlotChart.plotChartData = array;
[boxPlotChart drawChartGrid:array];
boxPlotChart = [[PlottingChart alloc] initWithFrame:NSMakeRect(10, -50, 850, 360) ]; // x,y lenght,height
[self.view addSubview:boxPlotChart];
}
Finally I found the solution.
Add initWithFrame method into NSView.
- (id)initWithFrame:(NSRect)frame dataArray:(NSMutableArray *)dtArray;
{
self = [super initWithFrame:frame];
self.plotChartData = dtArray;
return self;
}
And initial this one in NSViewController.
boxPlotChart = [[PlottingChart alloc] initWithFrame:NSMakeRect(10, -50, 850, 360) dataArray:array ];

How to set values of subclassed UIView properties when loading subclass from a xib

I have a subclassed UIView called BannerHeaderView, and designed the way I want it layed out in an xib. I have set the xib class to BannerHeaderView. I have a UILabel and a UIImageView which I have connected in IB.
The problem is that when I go to set the values of these subViews after initialising my BannerHeaderView in a ViewController, the label and image view are null. I have tried setting them in init also.
Code for BannerHeaderView.h:
#interface BannerHeaderView : UIView
#property (strong, nonatomic) IBOutlet UIImageView *bannerImage;
#property (strong, nonatomic) IBOutlet UILabel *headerLabel;
-(void)setTitle:(NSString *)title;
-(void)setImageFile:(PFFile *)imageFile;
#end
Code for BannerHeaderView.m:
#implementation BannerHeaderView
#synthesize headerLabel, bannerImage;
-(id)init{
self = [super init];
if (self) {
[self customInit];
}
return self;
}
-(id)initWithFrame:(CGRect)frame{
self = [super initWithFrame:frame];
if (self) {
[self customInit];
}
return self;
}
-(void)customInit{
UIView *contentView = [[[NSBundle mainBundle] loadNibNamed:#"BannerHeaderView"
owner:self
options:nil] objectAtIndex:0];
[self addSubview:contentView];
contentView.frame = self.bounds;
}
-(void)setTitle:(NSString *)title{
NSLog(#"HEADER = %#", headerLabel);
headerLabel.text = title;
}
And I am creating the BannerHeaderImage in my ViewController like so:
bannerHeader = [[BannerHeaderView alloc]initWithFrame:CGRectMake(0, 0, screenWidth, bannerHeight + segmentedHeaderHeight)];
[bannerHeader setTitle:#"I AM THE NEW TITLE"];
The log tells me that the headerLabel is null.
Questions:
How do I set the values of these subviews?
Should I just design the layout of this programatically?
Thanks for your time.
P.S. I have spent hours researching this and I can't find a solution. I did find similar questions on SO but none with suitable answers to enable me to solve my problem...
Please set the class BannerHeaderView to File's Owner like this

Derived UICollectionViewCell always returns null from dequeueReusableCellWithReuseIdentifier

I'm adding a UICollectionView programmatically to a controller, but no matter how I set it up, I can't get a valid UICollectionViewCell when calling dequeueReusableCellWithReuseIdentifier. Before showing the code, some info that might be helpful:
I'm using the latest XCode
I'm targeting iOS 8.1 on iPad
I'm not using a storyboard
I have a navigation controller setup and I'm also using Core Data
Here's the code:
Controller.h
#interface ViewController : UIViewController<UIImagePickerControllerDelegate, UICollectionViewDelegate, UICollectionViewDataSource>
#property (nonatomic, strong) NSManagedObjectContext *managedObjectContext;
#end
Controller.m
#interface ViewController ()
#property (strong, nonatomic) NSMutableArray *images;
#property (strong, nonatomic) UICollectionView *collectionView;
#end
// called by a button in the navigation bar
- (void)addMedia:(id)sender {
// load test images
if ([self.images count] == 0) {
NSBundle *myBundle = [NSBundle mainBundle];
NSArray *imagesPaths = [myBundle pathsForResourcesOfType:#"png" inDirectory:nil];
for (NSString *path in imagesPaths) {
UIImage *newImage = [[UIImage alloc] initWithContentsOfFile:path];
[self.images addObject:newImage];
}
self.introLabel.hidden = YES;
CGRect rect = CGRectMake(self.view.frame.size.width / 2 - 250,
self.view.frame.size.height / 2 - 250, 500, 500);
UICollectionViewFlowLayout *layout = [[UICollectionViewFlowLayout alloc] init];
layout.itemSize = CGSizeMake(120, 120);
layout.minimumInteritemSpacing = 10;
self.collectionView = [[UICollectionView alloc] initWithFrame:rect collectionViewLayout:layout];
UINib *cellNib = [UINib nibWithNibName:#"ImageViewCell" bundle:nil];
[self. collectionView registerNib:cellNib forCellWithReuseIdentifier:#"imageCell"];
//[self.collectionView registerClass:[ImageViewCell class] forCellWithReuseIdentifier:#"imageCell"];
[self.collectionView setDelegate:self];
[self.collectionView setDataSource:self];
[self.view addSubview:self.collectionView];
}
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self.images count];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
// THIS IS ALWAYS NULL
ImageViewCell *cell = (ImageViewCell *)[collectionView dequeueReusableCellWithReuseIdentifier:#"imageCell" forIndexPath:indexPath];
cell.image.image = [self.images objectAtIndex:indexPath.row];
return cell;
}
ImageViewCell.h
#interface ImageViewCell : UICollectionViewCell
#property (strong, nonatomic) IBOutlet UIImageView *image;
#end
ImageViewCell.m
#implementation ImageViewCell
- (id)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
// THIS IS ALWAYS NULL!
return self;
}
#end
In the ImageViewCell.xib I have a UICollectionCellView as the main view, which contains the UIImageView I'm trying to populate; the UICollectionCellView points to ImageViewCell (the derived class).
I should mention that I tried the same approach with a new project with a single controller and adding programmatically the UICollectionView and it works, so I must be missing something silly or doing something slightly different but I'm not aware of it.
[EDIT]: changed the code with solution.
Make sure in the xib file that the File's Owner property indicates the class name that implements it. Then, implement:
- (NSString *)reuseIdentifier {
return #"imageCell";
}
in your ImageViewCell implementation. There also might be a way to set this in interface builder, rather than overriding the getter.
By the way, if your ImageViewCell is backed by a xib, initWithFrame: will not be the designated initializer, but instead initWithCoder will be. But your implementation is fine as is, and you don't necessarily need to override initWithCoder at this point.
EDIT: as rdelmar pointed out, you should definitely be using the registerNib version as well; you wouldn't need to implement the reuseIdentifier getter this way.

EXC_BAD_ACCESS in UIWebView delegate

I've got a problem - I'm getting EXC_BAD_ACCESS when trying to set UIWebView.delegate = self;
My code:
vkLogin.h -
#import UIKit/UIKit.h
#interface vkLogin : UIViewController <UIWebViewDelegate>
{
UIWebView *authBrowser;
UIActivityIndicatorView *activityIndicator;
}
#property (nonatomic, retain) UIWebView *authBrowser;
#property (nonatomic, retain) UIActivityIndicatorView *activityIndicator;
#end
vkLogin.m -
#import "vkLogin.h"
#import "bteamViewController.h"
#implementation vkLogin
#synthesize authBrowser;
- (void) viewDidLoad
{
[super viewDidLoad];
activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleWhiteLarge];
activityIndicator.center = CGPointMake(self.view.bounds.size.width / 2, self.view.bounds.size.height / 2);
activityIndicator.autoresizesSubviews = YES;
activityIndicator.hidesWhenStopped = YES;
[self.view addSubview: activityIndicator];
[activityIndicator startAnimating];
authBrowser = [[UIWebView alloc] initWithFrame:self.view.bounds];
authBrowser.delegate = self;
authBrowser.scalesPageToFit = YES;
[self.view addSubview:authBrowser];
NSString *authLink = #"http://api.vk.com/oauth/authorize?client_id=-&scope=audio&redirect_uri=http://api.vk.com/blank.html&display=touch&response_type=token";
NSURL *url = [NSURL URLWithString:authLink];
[authBrowser loadRequest:[NSURLRequest requestWithURL:url]];
}
- (void) webViewDidFinishLoad:(UIWebView *)authBrowser
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Lol" message:#"OLOLO" delegate:self cancelButtonTitle:#"Okay" otherButtonTitles:nil, nil];
[alert show];
}
#end
So, if i'm commeting delegate string - everything working fine, but I didn't recieve my webViewDidFinishLoad event.
What I'm doing wrong?
The error isn't in the code you have posted. Your zombie message is saying your reference to vkLogin is bad. So you need to look at whatever class creates and holds a reference to your vkLogin class.
That class should be doing something like a vkLogin *foo = [[vkLogin alloc] init];
Update:
Based on your comments it looks like you are creating a local variable for vkLogin. It would be most useful to see the code creates and uses vkLogin and how it's called. Barring that, here are a few guesses.
You are called the method which creates and adds vkLogin to a subView more than once. (Each time would create a new instance).
You have some sort of call back which can occur after vkLogin has been removed.
My guess is vkLogin should be a property in your class, not a local method variable.
in your .h you would add
#proprerty (strong, nonatomic) vkLogin *vk;
and in your .m file you could refer to it as self.vk so you'd create it and add it as a subview like:
self.vk = [[vkLogin alloc] init];
[self.view addSubview:self.vk];
On a side note, convention says we should start class names with a capital letter, so you'd name the class VkLogin which would make it easily distinguishable from a variable named vkLogin (but worry about that after you solve the problem)

iOS: get image label

I have this code:
- (IBAction) checkIt:(id)sender{
NSString *button = [[(UIImageView *)sender label]text];
I want to get the label of the UIImageView. What am I doing wrong? This works with buttons...Not sure I understand how to access attributes correctly.
Subclass UIImageView. Add a string member and property for accessing it. Instead of creating an object of UIImageView, create the object of your class.
In .h
#interface CustomImageView : UIImageView
{
NSString *imageName;
}
#property (nonatomic, retain) NSString *imageName;
#end
in .m
#implementation CustomImageView
#synthesize imageName;
-(void) dealloc
{
[imageName release];
[super dealloc];
}
#end
in the file where you want to use this class
-(void) addCustomImageView
{
CustomImageView *imgView = [[CustomImageView alloc]initWithImage:[UIImage imageNamed:#"abc.png"]];
imgView.frame = CGRectMake(0, 0, 100, 100);
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc]initWithTarget:self action:#selector(imgViewtapped:)];
[imgView addGestureRecognizer:tap];
[tap release];
[self.view addSubview:imgView];
[imgView release];
}
-(NSString *) imgViewtapped:(CustomImageView *)sender
{
return [sender imageName];
}
UIImageViews do not have labels.
https://developer.apple.com/library/ios/#documentation/uikit/reference/UIImageView_Class/Reference/Reference.html