I created in .h file #property (for example BOOL value). In .m file i change BOOL value.
In subclass code i want to get value of this property NSLog(#"%#", _value) , but value is always null.
Base class code:
.h file:
#interface CommonViewController : UIViewController <MPPGraphDelegate, MPPInputSourceDelegate>
...
#property(nonatomic) BOOL buttonState;
#property(nonatomic) UIButton* button;
...
#end
.mm file:
- (void)viewDidLoad {
[super viewDidLoad];
...
_button = [UIButton buttonWithType:UIButtonTypeCustom];
[_button addTarget:self
action:#selector(aMethod:)
forControlEvents:UIControlEventTouchUpInside];
[_button setTitle:#"Show View" forState:UIControlStateNormal];
_button.frame = CGRectMake(100, 500, 120, 30);
[self.view addSubview:_button];
}
-(void)aMethod:(UIButton*) sender {
if (sender.isSelected) {
sender.selected = NO;
_buttonState = NO; <-- change value
} else {
sender.selected = YES;
_buttonState = YES; <-- change value
}
}
Subclass code
.h file:
#interface HandTrackingViewController : CommonViewController
...
#end
.mm file:
#implementation HandTrackingViewController
#synthesize buttonState = _buttonState;
- (void)someMethod {
NSLog(_buttonState ? #"YES" : #"NO"); <-- _buttonState always null
}
#end
self.buttonState without #synthesize solved my problem
Related
Please help me, I have been customizing a UIView class to set NSString value as a tag, but how can I get that view from view hierarchy.In UIView class default method to get view is viewWithTag:(NSInteger).
Please see below code
#import <UIKit/UIKit.h>
#interface UIView (StringTag)
#property (nonatomic, copy) NSString *tagString;
#end
#import "UIView+StringTag.h"
#import <objc/runtime.h>
static const void *tagKey = &tagKey;
#implementation UIView (StringTag)
- (void)setTagString:(NSString *)tagString
{
objc_setAssociatedObject(self, tagKey, tagString,OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (id)tagString
{
return objc_getAssociatedObject(self, tagKey);
}
#end
I want a method like viewWithStringTag:(NSString *)stringTag.
Thanks,
Use recursive search, includes self
#import <UIKit/UIKit.h>
#interface UIView (StringTag)
#property (nonatomic, copy) NSString *tagString;
- (UIView *)viewWithStringTag:(NSString *)strTag;
#end
#import "UIView+StringTag.h"
#import <objc/runtime.h>
static const void *tagKey = &tagKey;
#implementation UIView (StringTag)
- (void)setTagString:(NSString *)tagString
{
objc_setAssociatedObject(self, tagKey, tagString,OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (id)tagString
{
return objc_getAssociatedObject(self, tagKey);
}
- (UIView *)viewWithStringTag:(NSString *)strTag{
if ([self.tagString isEqual:strTag]){
return self;
}
if (!self.subviews.count){
return nil;
}
for (UIView *subview in self.subviews){
UIView *targetView = [subview viewWithStringTag:strTag];
if (targetView){
return targetView;
}
}
return nil;
}
#end
Here are my testing code
- (void)viewDidLoad {
[super viewDidLoad];
UIView *aView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
aView.tagString = #"aView";
UIView *bView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 100, 100)];
bView.tagString = #"bView";
[self.view addSubview:aView];
[aView addSubview:bView];
UIView *targetView = [self.view viewWithStringTag:#"bView"];
NSLog(#"%#", targetView);
// <UIView: 0x7f933bc21e50; frame = (0 0; 100 100); layer = <CALayer: 0x7f933bc1c430>>
}
HomeViewController.h
#import "DataParser.h"
#interface HomeViewController : UIViewController <DataParserDelegate>
{
UILabel *theLabel;
}
HomeViewController.m
#import "HomeViewController.h"
#implementation HomeViewController
-(void)viewDidLoad
{
theLabel = [[UILabel alloc] initWithFrame:CGRectMake(200, 200, 100, 30)];
theLabel.text = #"Bob";
theLabel.font = [UIFont italicSystemFontOfSize:20.0];
theLabel.textColor = [UIColor whiteColor];
theLabel.backgroundColor = [UIColor blueColor];
[self.view addSubview:theLabel];
UIButton *theButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[theButton addTarget:self action:#selector(clicked:) forControlEvents:UIControlEventTouchUpInside];
[theButton setTitle:#"Big Button" forState:UIControlStateNormal];
theButton.frame = CGRectMake(100,100,200,50);
[self.view addSubview:theButton];
}
-(void)clicked:(id)sender
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND,0),
^{
DataParser *data = [[DataParser alloc] init];
data.delegate = self;
[data loadSomething];
dispatch_async(dispatch_get_main_queue(),
^{
NSLog(#"Thread done");
});
});
}
-(void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
{
theLabel.frame = CGRectMake(250,250,100,30);
theLabel.text = #"This message displays fine";
}
-(void)loadMessage:(NSString *)message
{
NSLog(#"Received message: %#", message);
theLabel.frame = CGRectMake(300,300,100,30);
theLabel.text = #"This message won't display";
}
#end
DataParser.h
#protocol DataParserDelegate;
#interface DataParser : NSObject
#property (weak, nonatomic) id <DataParserDelegate> delegate;
-(void)loadSomething;
#end
#protocol DataParserDelegate <NSObject>
-(void)loadMessage:(NSString *)message;
#end
DataParser.m
#import "DataParser.h"
#implementation DataParser
#synthesize delegate=_delegate;
-(void)loadSomething
{
[[self delegate] loadMessage:#"ASDF"];
}
#end
-=-=-=-=-=-=-=-=-=-=-=-=-=-
Basically, I create a label and add it to the screen. At this point you can clearly see a Blue button with white text saying "Bob" on it. When you rotate the screen, the button changes text and position just fine. However, if I click the button, it creates a dataParser object, sets the delegate to self, and calls "loadSomething". Within the dataParser object, "loadSomething" merely calls the delegate method "loadMessage".
The question is, when "loadMessage" gets called, the NSLog statement prints correctly ("Received message: ASDF"), however, theLabel doesn't move and doesn't change its text. Why is this? And how do I fix this issue?
Try this code :
-(void)loadMessage:(NSString *)message
{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"Received message: %#", message);
theLabel.frame = CGRectMake(300,300,100,30);
theLabel.text = #"This message displays great!";
});
}
It should run it on the main thread.
I have a UIButton which calls a method from another UIViewController, that method calls a delegate method which is not happening.
Something like:
FirstViewController
-(void)viewWillAppear:(BOOL)animated {
//Submit Button
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button addTarget:self
action:#selector(someMethod)
forControlEvents:UIControlEventTouchDown];
[button setTitle:#"Submit" forState:UIControlStateNormal];
button.frame = CGRectMake(100.0, 120.0, 80.0, 40.0);
[self addSubview:button];
}
- (void)someMethod {
SecondViewController *viewC = [[SecondViewController alloc] init];
[viewC otherMethod];
}
SecondViewController
- (void)otherMethod {
NSLog(#"Verification.....");
[self.delegate foo:self Bar:self.text]; //not working when called the otherMethod from FirstViewController
}
I know I'm doing it wrong way.
A very simple example of the way protocols and delegates work in objective-c
#class A;
#protocol DelegateName<NSObject>
#optional
- (void)doSomething:(NSString *)text;
#end
#interface A: NSObject {
NSString *bar;
id <DelegateName> delegate;
}
#property (nonatomic, retain) NSString *bar;
#property (nonatomic, assign) id <DelegateName> delegate;
- (void)someAction;
#end
This is your protocol declaration.
Then when you are calling the delegate method, you need an object of the class to invoke the delegate method. In your case it is vc. You set delegate like this:
[vc setdelegate: self];
Then you invoke method, like you have done.
See if you are missing any point from this example.
Try to understand how delegate methods work .
#protocol CPUPerformanceDelegate <NSObject>
-(void)getUsedCpuOperations:(float)percent;
-(void)getKernelCpuOperations:(float)percent;
-(void)getIdleCpuOperations:(float)percent;
-(void)getUserCpuOperations:(float)percent;
-(void)getNiceCpuOperations:(float)percent;
#end
#interface CPUPerformance : NSObject{
processor_info_array_t cpuInfo, prevCpuInfo;
mach_msg_type_number_t numCpuInfo, numPrevCpuInfo;
unsigned numCPUs;
NSLock *CPUUsageLock;
}
#property(nonatomic,assign)id<CPUPerformanceDelegate>delegate;
#property(nonatomic,retain)NSTimer *updateTimer;
#end
Then
#import "CPUPerformance.h"
#implementation CPUPerformance
#synthesize delegate,updateTimer;
- (void)updateInfo
{
idlepercent = ((idle/total)*100);
userpercent = (user/total)*100;
syspercent = (sys/total)*100;
nicepercent = (nice/total)*100;
inUsepercent = (inUse/total)*100;
[delegate getIdleCpuOperations:idlepercent];
[delegate getKernelCpuOperations:syspercent];
[delegate getNiceCpuOperations:nicepercent];
[delegate getUsedCpuOperations:inUsepercent];
[delegate getUserCpuOperations:userpercent];
}
and finally
#import "CPUPerformance.h"
#interface SpecProjectFirstViewController : UIViewController<UITableViewDataSource,UITableViewDelegate,CPUPerformanceDelegate>{
//Ivars
NSMutableArray *processArray;
//User Interface Object
UILabel *cpuUsage;
UILabel *cpuIdle;
UILabel *cpuUser;
UILabel *cpuNice;
UILabel *cpuKernel;
IBOutlet UITableView *tableViews;
CPUPerformance *cpuObject;
}
=================
#import "SpecProjectFirstViewController.h"
#implementation SpecProjectFirstViewController
-(void)getIdleCpuOperations:(float)percent{
[cpuIdle setText:nil];
[cpuIdle setText:[NSString stringWithFormat:#"Idle :%.0f %%",percent]];
[cpuIdle setTextAlignment:UITextAlignmentCenter];
}
-(void)getKernelCpuOperations:(float)percent{
[cpuKernel setText:nil];
[cpuKernel setText:[NSString stringWithFormat:#"Kernel :%.0f %%",percent]];
[cpuKernel setTextAlignment:UITextAlignmentCenter];
}
-(void)getNiceCpuOperations:(float)percent{
[cpuNice setText:nil];
[cpuNice setText:[NSString stringWithFormat:#"Nice :%.0f %%",percent]];
[cpuNice setTextAlignment:UITextAlignmentCenter];
}
-(void)getUsedCpuOperations:(float)percent{
[cpuUsage setText:nil];
[cpuUsage setText:[NSString stringWithFormat:#"Used :%.0f %%",percent]];
[cpuUsage setTextAlignment:UITextAlignmentCenter];
}
It is customary to validate that the delegate responds to the method you want to call, so your otherMethod method should be implemented like this, adding more logging to help debug:
- (void)otherMethod
{
NSLog(#"delegate = %p", self.delegate);
if ([self.delegate respondsToSelector:#selector(foo::)])
{
NSLog(#"Calling delegate foo");
[self.delegate foo:self Bar:self.text];
}
else
{
NSLog(#"Delegate doesn't respond to foo");
}
}
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
I trying to extend UIButton but I keep getting a "EXC_BAD_ACCESS", inside the initializer of ColorButton's implementation file.
Header of ColorButton.
#import <Foundation/Foundation.h>
#interface ColorButton : UIButton {
UIImage * originalImage;
}
#property (nonatomic,readonly) NSString * buttonName;
-(id) initButtonWithName:(NSString *) color;
-(void) setOriginalImage;
-(void) setImage:(UIImage *) image;
#end
ColorButton Implementation
#import "ColorButton.h"
#implementation ColorButton
#synthesize buttonName;
-(id) initButtonWithName:(NSString *) color {
if ((self = (ColorButton *)[UIButton buttonWithType:UIButtonTypeCustom])) {
buttonName = color;
[self setTitle:buttonName forState:UIControlStateNormal]; //This is the line of the "EXC_BAD_ACCESS" error.
[self setBackgroundImage:[self backgroundImageForDevice:color] forState:UIControlStateNormal]; // This line gets the error too. If I comment the line before it out.
}
return self;
}
-(UIImage *) backgroundImageForDevice:(NSString *) color {
color = [color stringByAppendingString:#"Bubble"];
if ([[[UIDevice currentDevice] model] isEqualToString:#"iPad"] ||[[[UIDevice currentDevice] model] isEqualToString:#"iPad Simulator"]) {
color = [color stringByAppendingString:#"-iPad"];
}
color = [color stringByAppendingString:#".png"];
return [UIImage imageNamed:color];
}
-(void) setOriginalImage {
[self setBackgroundImage:originalImage forState:UIControlStateNormal];
}
-(void) setImage:(UIImage *) image {
[self setImage:image forState:UIControlStateNormal];
}
#end
You can not cast a UIButton * instance to a ColorButton * type.
You have to remember that you ColorButton inherits from UIButton and not the other way, this means that every instance of ColorButton is a UIButton by definition, but the opposite is not true.
Here is another thread that has the exact same issue :)
objective C: Buttons created from subclass of UIButton class not working