Accessor method is not called - objective-c

I'm trying to build a dynamic marquee using the solution provided in this article:
How To Create Dynamic more than one uiview with Marquee Effect in iphone
The problem ins that method accessor. Thats how I implemented in my view controller:
gridViewController.h
#import "CrawlView.h"
CrawlView *marquee;
#property (strong, nonatomic) CrawlView *marquee;
gridViewController.m
#synthesize marquee;
....
[marquee setMessages:self.noticiasArray];
[marquee go];
I put a break point in the accessor method, but it's never called:
- (void)setMessages:(NSMutableArray *)messages {
if (_messages != messages) {
_messages = messages;
[self buildSubviews];
}
}
So the marquee is not shown.
I will appreciate your help on this.
thnaks

You need to set it to #dynamic
#dynamic marquee;
instead of #synthesize marquee; in order to use your custom setter

Try self.marquee to call the accessor method.

Related

Update UILabel text from another class in Objective-C

I have a method implemented in the ViewCotroller class to set the message to a UILable in that class.
-(void)setAuthenticationMessage:(NSString *)message{
//lblStatus is the UILabel
lblStatus.text = message;
}
I'm accessing this method from another class to set the message. Though code executes correctly this message didn't update. I tried it by executing this method in a different thread. But that was also unsuccessful. Can anyone help me to figure out the issue?
What are lblStatus's memory management properties? Your naming convention alone leads me to believe that it is something to do with this. Usually you refer to instance variables as:
_lblStatus or self.lblStatus
use #protocol & delegates to access another class refer this link example example2
Use the delegate design pattern (google it). Example:
//In the updating class .h
#protocol LabelChangerDelegate <NSObject>
-(void)handleLabelChangeMessage;
#end
#property (assign, nonatomic) id <LabelChangerDelegate> delegate;
//In the updating class .m
-(void)changeLabelInOtherClass{
if (self.delegate != nil && [self.delegate respondsToSelector:#selector(handleLabelChangeMessage)]) {
[self.delegate performSelector:#selector(handleLabelChangeMessage)];
}
} else {
NSLog(#"Delgate doesn't implement handleLabelChangeMessage");
}
//In the view controller .h
<LabelChangerDelegate>
-(void)viewDidLoad{
//set the delegate to self
}
//In the view controller .m
-(void)handleLabelChangeMessage{
self.label.text=#"I changed through delegation";
}
Another option is to use NSNotificationCenter

Why my custom delegate method does not receive the call?

I would like to send the message from HelloWorldLayer, and receive it in ScoreLayer, in order to update the label. The CCLOG(#"///addNewScore"); works fine, but then updateScore, in ScoreLayer, does not receive the call, would you know why? Here's my code : (edit: i tried with "retain" in #property, but nothing changes) :
#interface HelloWorldLayer : CCLayer
{
//...
id<ScoreDelegate>delegate;
}
#property (nonatomic,retain) id <ScoreDelegate> delegate;
#implementation HelloWorldLayer
#synthesize delegate;
//...
-(void)addNewScore:(int)num{
CCLOG(#"///addNewScore");//works fine
[delegate updateScore:num];
}
#import <Foundation/Foundation.h>
#protocol ScoreDelegate
-(void)updateScore:(int)num;
#end
#interface ScoreLayer : CCLayer <ScoreDelegate>{
//...
}
-(void)updateScore:(int)num{
CCLOG(#"hello");//DOES NOT WORK
}
#end
Thanks a lot
I suspect that the ScoreLayer is being released before your call. I'm not too familiar with assign, I have only written ARC Objective-C; but I think it is roughly the same as weak (as it should be for delegates). This means that in order for that pointer to be valid, someone else in the application needs to "own" the ScoreLayer.
Now, that being said, I've only assumed that you are properly connecting the two objects in the first place. There isn't code posted which shows that, but this matter of a possibly-released ScoreLayer is important enough to keep in mind either way.
You would declare that protocol (delegate method) in the interface file of HelloWorldLayer. You would then put the delegate method inside ScoreLayer.m:
-(void)updateScore:(int)num {
// Do something
}
The way it is now, you declared the protocol in the wrong class.

accessing superview properties

I've searched for the answer to this question, and the answers I'm finding don't work.
I have a view that is a subclass of UIView to which I've added a property. I would like to access this property from the subviews created by this view. Is that possible?
I've tried referring to self.superview.propertyname but I get an error that propertyname is not found on object of type UIView. Well, right. I realize that since it's a subclass of UIView, it's a UIView, but how can I get it to know about the extra property I added?
You have a number of options, two of them are:
1. Casting:
#implementation SubviewView
- (void)blah
{
((CustomView *)self.superview).property = ...`
}
#end
2. Delegates:
#protocol SubviewViewDelegate
- (void)customView:(SubView *)sv modified:(...)value;
#end
#class SubView
#property (nonatomic, weak) id <CustomViewDelegate> delegate;
#end
#implementation SubviewView
- (void)blah
{
[self.delegate subView modified:...];
}
#end
#implementation CustomView
- (void)subView:(SubView *)sv modified:(...)value
{
self.property = value;
}
#end
Although the second option is more code, I think it is often better suited. Using delegates reduces coupling and works nicely with the Law of Demeter. For more info see this documentation.

Passing setters/getters of an instance variable up to a class

I'm working on creating a UIView subclass (which I'm calling MarqueeLabel) that animates a subview UILabel ivar in a marquee fashion when the UILabel text is too long for the containing view.
I was hoping to have a clean implementation, without having to write methods in my MarqueeLabel class just to set/retrieve all the the standard UILabel (text, font, color, etc) instance variables of the UILabel ivar. I've found a way to do this with message forwarding - all unrecognized methods sent to MarqueeLabel are passed on to the UILabel ivar. In my case the methods unrecognized by MarqueeLabel are the methods typically used with UILabel.
There are some problems with that approach though:
1. You have to use [marqueeLabel setText:#"Label here"], rather than marqueeLabel.text
2. The compiler gives warnings on the above line, because:
'MarqueeLabel' may not respond to '-setText:'
which I would know to ignore but would annoy anyone else.
To avoid these problems, is there any way to "bring forward" the methods an ivar so that they're accessible to something using the class while still acting upon the ivar object?
Thanks!
Note: The way I've set this up may not be the best way to do it either. Perhaps subclassing or class continuing UILabel would be better, but I wasn't able to grasp how the animation + clipping (when the text scrolling off moves out of containing UIView and disappears) could be done using those methods.
Note 2: I know you can use marqueeLabel.subLabel.text where subLabel is the subview UILabel. And this may be the direction I take, but might as well see if there's a better solution!
For properties, you could define a property in the interface and use #dynamic in the implementation so that you can don't have to create stub implementations. Make sure you also override valueForUndefinedKey: and setValue:forUndefinedKey: and forward to your label.
For any methods which are not part of a property, you can use a category to declare the method without implementing it. This will get rid of warnings but still use the builtin forwarding.
//MarqueeLabel.h
#import <UIKit/UIKit.h>
#interface MarqueeLabel : UIView {}
#property (nonatomic, copy) NSString *text;
#end
#interface MarqueeLabel (UILabelWrapper)
- (void)methodToOverride;
#end
//MarqueeLabel.m
#import "MarqueeLabel.h"
#implementation MarqueeLabel
#dynamic text;
- (id)valueForUndefinedKey:(NSString *)key {
return [theLabel valueForKey:key];
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key {
[theLabel setValue:value forKey:key];
}
#end

Can an inherited #property not satisfy a <protocol> #property?

I've got a protocol:
#protocol Gadget <NSObject>
#property (readonly) UIView *view;
- (void) attachViewToParent:(UIView *)parentView;
#end
And an "abstract" base class, with an implementation (as a getter, not shown) of -(UIView *)view:
// Base functionality
#interface AbstractGadget : NSObject {
UIView *view;
}
#property (readonly) UIView *view;
#end
But when I implement the Gadget protocol in a subclass of AbstractGadget, like so:
// Concrete
#interface BlueGadget : AbstractGadget <Gadget> {
}
- (void) attachViewToParent:(UIView *)parentView;
#end
#implementation BlueGadget
- (void) attachViewToParent:(UIView *)parentView {
//...
}
#end
I get a compiler error telling me "warning: property 'view' requires method '-view' to be defined." I can make this go away using #dynamic, or adding a stub method:
- (UIView *) view {
return [super view];
}
But I just want to know if I'm doing something that's not supported, something I shouldn't be doing, or if it's just a limitation / bug in the compiler?
By declaring the property as #dynamic you are telling the compiler that the property getter (and setter if required) are implemented elsewhere (potentially at runtime). This sounds like a perfectly reasonable use case to me.
See The Docs for more information.
I also came across this exact issue. This is one of situations that #dynamic is there for.
Here is the rule for variable, property and synthesize in objective-C:
If you have a property, you must have a #synthesize or you declare #dynamic and write the getter and setter method yourself.
So, because you have a property called view, you have to declare #synthesize. That should be it. Nothing to do with #protocol, inheritance