I want to use an static function from a protocol in a function:
#implementation IPadPanoramaViewController
- (void)viewDidLoad
{
[self.view addSubview:[PanoramaContent getPanoramaContentByPanoramaItem:[[PanoramaListItem alloc] init]];
[super viewDidLoad];
}
#end
#protocol PanoramaItemProtocol
+ (UIView *) getPanoramaItemBySection;
#end
#implementation PanoramaContent
+ (UIView *) getPanoramaContentByPanoramaItem:(id<PanoramaItemProtocol>) itemKind {
return [itemKind getPanoramaItemBySection]; //here is the problem "unrecognized selector sent to instance"
}
#end
I wish "PanoramaListItem" don't be a NSObject
The problem is that you've defined getPanoramaBySection to be a class method, when you're calling it on an instance. In the protocol declaration, replace the + with a -.
First, static methods can only be sent to a class. If you don't want to create an object, the parameter of getPanoramaContentByPanoramaItem: should be of type Class. You can use something like the following:
+ (UIView *) getPanoramaContentByPanoramaItem:(Class)itemKind {
UIView *v = nil;
if( [itemKind respondsToSelector:#selector(getPanoramaItemBySection)] ) {
v = [itemKind getPanoramaItemBySection];
}
return v;
}
and to send the message:
[self.view addSubview:[PanoramaContent getPanoramaContentByPanoramaItem:[PanoramaListItem class]]];
Related
I'm trying to add a convenience constructor to my custom object.
Similar to [NSArray arrayWithArray:]
I know it involves a class method that returns an auto released object. I've been googling around but all I can seem to find is the definition of a convenience constructor but not how to write one.
Let's say you have the following:
#class PotatoPeeler : NSObject
- (instancetype)initWithWidget: (Widget *)w;
#end
Then to add a factory method, you'd change it to this:
#class PotatoPeeler : NSObject
+ (instancetype)potatoPeelerWithWidget: (Widget *)w;
- (instancetype)initWithWidget: (Widget *)w;
#end
And your implementation would simply be:
+ (instancetype)potatoPeelerWithWidget: (Widget *)w {
return [[[self alloc] initWithWidget: w] autorelease];
}
Edit: replaced id with instancetype. They are functionally identical, but the latter provides better hints to the compiler about the method's return type.
Generally my approach is the following: first I create a normal initializer method (instance method), then I create a class method that calls the normal initializer. It seems to me Apple uses the same approach most of the time. An example:
#implementation SomeObject
#synthesize string = _string; // assuming there's an 'string' property in the header
- (id)initWithString:(NSString *)string
{
self = [super init];
if (self)
{
self.string = string;
}
return self;
}
+ (SomeObject *)someObjectWithString:(NSString *)string
{
return [[[SomeObject alloc] initWithString:string] autorelease];
}
- (void)dealloc
{
self.string = nil;
[super dealloc];
}
#end
I am trying to set the value of an NSTextField, but it's not working properly.
I have a button linked to an IBAction, and when I set it using self, it works fine:
#import <Foundation/Foundation.h>
#interface TestMessage : NSObject {
IBOutlet NSTextField *text;
}
- (IBAction) setMessage: (id) controller;
- (void) Message:(NSString *) myMessage;
#end
#import "TestMessage.h"
#implementation TestMessage
- (IBAction) setMessage: (id) controller {
// This works
[self Message:#"Hello"];
// but this doesn't
TestMessage * messageTest= [TestMessage new];
[messageTest Message:#"Hi"];
}
- (void) Message: (NSString *) myMessage {
[text setStringValue: myMessage];
NSLog(#"Message Was Called");
// This returns <NSTextField: 0x1001355b0> when called
// using self, but null when called the other way.
NSLog(#"%#", text);
}
#end
I've searched for a while, but still can't find the answer.
I guess it has something to do with the delegate, but I'm not sure.
Thanks in advance.
Are you sure message is called when you call it from anotherFuntion? If anotherFuntion is a method of another class, calling [self message:] won't work as you expected to...
I know this is an old post, but I have been fiddling with the same issue today.
You have to return string value in textfield:
[textField stringValue];
The code
TestMessage * messageTest = [TestMessage new];
is unusual, specifically new. I'm going to assume that new is just a class method does normal alloc/init equivalent to
TestMessage * messageTest = [[TestMessage alloc] init];
The main problem is that IBOutlet NSTextField *text will be initialized only if the class TestMessage is loaded with a Nib file. It would have to be named as the class of an object in Interface Builder, like so
and you would have to implement initWithCoder and encodeWithCoder something like this in order to extract your field value from the IB encoding:
- (instancetype)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
self.text = [coder decodeObjectForKey:#"text"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)coder
{
[super encodeWithCoder:coder];
[coder encodeObject:self.text forKey:#"text"];
}
Fundamentally, IBOutlet fields do not get wired up wherever you create an instance of that class. If they did, how would you express that field A should be wired to UI object A and field B should be wired to UI object B? The connection is established only in the context of loading a class from a Nib file.
I'm new to objective-c and I'm finding that I don't know how to correctly assert that a text property on some given label is equal to a raw string value. I'm not sure if I just need to cast the label as NSString or if I need to modify my assert statement directly.
#interface MoreTest : SenTestCase {
MagiczzTestingViewController* controller;
}
- (void) testObj;
#end
#implementation MoreTest
- (void) setUp
{
controller = [[MagiczzTestingViewController alloc] init];
}
- (void) tearDown
{
[controller release];
}
- (void) testObj
{
controller.doMagic;
STAssertEquals(#"hehe", controller.label.text, #"should be hehe, was %d instead", valtxt);
}
#end
The implementation of my doMagic method is below
#interface MagiczzTestingViewController : UIViewController {
IBOutlet UILabel *label;
}
#property (nonatomic, retain) UILabel *label;
- (void) doMagic;
#end
#implementation MagiczzTestingViewController
#synthesize label;
- (void) doMagic
{
label.text = #"hehe";
}
- (void)dealloc {
[label release];
[super dealloc];
}
#end
The build is fine when I modify the assert to compare a raw NSString to another but when I try to capture the text value (assuming it's of type NSString) it fails. Any help would be much appreciated!
STAssertEquals() checks for identity of the two values provided, so it's equivalent to doing this:
STAssertTrue(#"hehe" == controller.label.text, ...);
Instead, you want STAssertEqualObjects(), which will actually run an isEqual: check like the following:
STAssertTrue([#"hehe" isEqual:controller.label.text], ...);
You need to load the nib of the view controller. Otherwise there won't be any objects for the label outlet to be hooked up to.
One way to do this is to add an ivar for the view controller's view to your test case:
#interface MoreTest : SenTestCase {
MagiczzTestingViewController *controller;
UIView *view;
}
#end
#implementation MoreTest
- (void)setUp
{
[super setUp];
controller = [[MagiczzTestingViewController alloc] init];
view = controller.view; // owned by controller
}
- (void)tearDown
{
view = nil; // owned by controller
[controller release];
[super tearDown];
}
- (void)testViewExists
{
STAssertNotNil(view,
#"The view controller should have an associated view.");
}
- (void)testObj
{
[controller doMagic];
STAssertEqualObjects(#"hehe", controller.label.text,
#"The label should contain the appropriate text after magic.");
}
#end
Note that you also need to invoke super's -setUp and -tearDown methods appropriately from within yours.
Finally, do not use dot syntax for method invocation, it is not a generic replacement for bracket syntax in message expressions. Use dot syntax only for getting and setting object state.
I need to pass self into a method, how do I do it ?
I don't know what type of object self is ?
I've tried :(id)dg
When you are inside an #implementation block for a class Foo, self is Foo*. This means that you can type the method parameter as Foo* or id (= any object, no type checking done):
#class Foo, SomeCollaborator;
#interface SomeCollaborator
- (void) doSomethingWithMe: (Foo*) myself;
- (void) doSomethingWithMe2: (id) myself;
#end
#implementation Foo
- (void) someFooMethod {
[someCollaborator doSomethingWithMe:self];
}
#end
That seems right to me. (id) represents all possible objects.
Here's some code that works:
#implementation Inspector
- (void)printClassOf:(id)instance {
NSLog("instance is of class: %#", [instance class]);
}
#end
#implementation SomeClass
- (void)someMethod {
Inspector *myInstance = [[[Inspector alloc] init] autorelease];
[myInstance printClassOf:self];
}
#end
What is the signature of the method (in other words, how is the method defined in the interface)?
Or do you mean, you want to define a method in class B to allow an instance of class A to call that method and pass in itself as one of the parameters? If so, :(id)sender is often used as a generic way to do that. For example, in NSWindow,
- (void)makeKeyAndOrderFront:(id)sender;
- (void)orderFront:(id)sender;
- (void)orderBack:(id)sender;
Within the implementation of that method, you can do something like this to help determine what to do:
- (void)makeKeyAndOrderFront:(id)sender {
if ([sender isKindOfClass:[NSWindowController class]]) {
// do something
} else if ([sender isKindOfClass:[MyCoolClass class]]) {
// do something
} else if ([sender respondsToSelector:#selector(whyDidYouOrderMeFront)]) {
// do something
} else if ([sender conformsToProtocol:#protocol(someCoolProtocol)]) {
// do something
} else {
// do something
}
}
I initialize a view(Image) through:
Image *myImageView = [[Image alloc]init];
myImageView.myId = randomImageNumber;
[myImageView initWithImage:myImage];
At the Image class I do a Log(LOG1) and get the previously set randomImageNumber.
Later on, in the very same Class, I do a second Log(LOG2).
Why does my second log have no value anymore ?
Here my implementation-file of the Class Image:
#synthesize myId;
-(id) initWithImage: (UIImage *) anImage
{
NSLog(#"LOG1%d",myId);
if ((self = [super initWithImage:anImage]))
{
self.userInteractionEnabled = YES;
}
return self;
}
}
-(void)touchesBegan...
....
- (void) touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
NSLog(#"LOG2%d",myId);
}
The "return self" empties myId which i declared in the header-file and which was set at the initialisation.
How do I prevent that ?
my Headerfile looks like this:
#interface Image : UIImageView
{
int myId;
}
#property (assign) int myId;
#end
I think I found it:
https://www.google.com/maps/place/Variable/#53.626739,10.025728,17z/data=!3m1!4b1!4m2!3m1!1s0x47b1885360fab615:0x584b82c7dfb5f612
Can you check if this Variable is yours?
besties
phil
Couple things in your code. NEVER call init more than once on an object, that just screws up your object.
Change it to this:
Image *myImageView = [[Image alloc] initWithImage:myImage];
myImageView.myId = randomImageNumber;
That is your problem, by default when initializing a subclass of NSObject, all properties are set to 0 (or nil if they are pointers).
If you need to have a default value for myId then do this:
// Image.m
#implementation
// other code
-(id) initWithImage:(UIImage *) image
{
if (self = [super initWithImage:image])
{
self.myId = randomImageNumber;
}
return self;
}
// other code
#end