How to declare a function in Cocoa after the function using it? - cocoa

I'm slowly building my application to a working state.
I'm using two functions called setCollection and addToCollection. These functions both accept NSArray as input.
I also have a function called add in which I use both of these functions. When I try to compile, Xcode shows an error:
'setCollection' undeclared (first use in this function)
I guess this has to do with the function called being defined below the active function. Another guess would be that the functions should be globalized to be useable inside my add function.
I'm normally a php coder. the way Php handles this is the first one. The functions called should be before the functions using them, because otherwise they just don't exist. Is there a way to make functions still to come available at runtime, or should I rearrange all functions to make them function properly?

You can declare functions ahead of time as follows:
void setCollection(NSArray * array);
void addToCollection(NSArray * array);
//...
// code that calls setCollection or addToCollection
//...
void setCollection(NSArray * array)
{
// your code here
}
void addToCollection(NSArray * array)
{
// your code here
}
If you are creating a custom class, and these are member functions (usually called methods in Objective-C) then you would declare the methods in your class header and define them in your class source file:
//MyClass.h:
#interface MyClass : NSObject
{
}
- (void)setCollection:(NSArray *)array;
- (void)addToCollection:(NSArray *)array;
#end
//MyClass.m:
#import "MyClass.h"
#implementation MyClass
- (void)setCollection:(NSArray *)array
{
// your code here
}
- (void)addToCollection:(NSArray *)array
{
// your code here
}
#end
//some other source file
#import "MyClass.h"
//...
MyClass * collection = [[MyClass alloc] init];
[collection setCollection:someArray];
[collection addToCollection:someArray];
//...

If your functions are global (not part of a class), you just have to put the declaration before the use, just like eJames suggests.
If your functions actually are methods (part of a class), you have to declare an anonymous category of your class before the implementation and put your method declarations in this interface:
#interface Myclass()
- (void) setCollection:(NSArray*)array;
- (void) addToCollection:(NSArray*)array;
#end
#implementation Myclass
// Code that calls setCollection or addToCollection
- (void) setCollection:(NSArray*)array
{
// your code here
}
- (void) addToCollection:(NSArray*)array
{
// your code here
}
#end
This way, you don't need to expose your functions in the main interface of MyClass.

Related

Xamarin iOS binding library duplicated constructors issue

I have an issue with duplicated constructor in Xamarin iOS binding library with code generated by sharpie tool from third-party SDK code. Basicly C# generated interface is using NSFileHandle as a base type and SDK header file declares identical designated initializer in its subclass like in NSFileHandler so I'm getting "Member ... is already defined error" because now binding library is generating C# constructor twice - first time from the base class and the second from subclassed initializer.
Objective-C code:
#interface MyFileHandle : NSFileHandle
//...
- (nullable instancetype)initWithCoder:(NSCoder *)coder NS_DESIGNATED_INITIALIZER;
//...
C# binding library code:
[BaseType(typeof(NSFileHandle))]
public interface MyFileHandle
{
//...
[Export("initWithCoder:")]
[DesignatedInitializer]
IntPtr Constructor(NSCoder coder);
//...
}
Binding library generated code (*.g.cs):
[Register("MyFileHandle", true)]
public unsafe partial class MyFileHandle : NSFileHandle {
//...
[CompilerGenerated]
[DesignatedInitializer]
[EditorBrowsable (EditorBrowsableState.Advanced)]
[Export ("initWithCoder:")]
public MyFileHandle (NSCoder coder) : base (NSObjectFlag.Empty)
{
//...
}
[Export ("initWithCoder:")]
[DesignatedInitializer]
[CompilerGenerated]
public MyFileHandle (NSCoder coder)
: base (NSObjectFlag.Empty)
{
//...
}
//...
}
How can I prevent binding library from generating constructors twice thus get rid of the error?
It seems that you can simply remove duplicated Constructor from ApiDefinitions.cs as #SushiHangover suggested.

Invoke a method from another class, without reinitializing it

I've a ViewController where I call a method from another class (TCP class), where I make a TCP connection to a server, that gives me a response. And I want to, when that TCP class, get's the response from the server, call another method from the ViewController.
Problems:
I'm a noob.
I'm initializing and allocating that first
Viewcontroller on the TCP, and all my vars are reseted (something
that I don't want).
So... What can I do to make it right? I just want to call a method from a different class, that is already allocated in memory.
Tks!
You could set up the ViewController as an observer to the TCP class. This is a link that explains an implementation of the observer pattern in Obj-C. (Very similar to what I use but in a nice write up.)
http://www.a-coding.com/2010/10/observer-pattern-in-objective-c.html
I usually like to separate the persistence layer from the interface as well. I use observers or KVO to notify my business logic and view controllers that something changed.
You can also send the information through the Notification Center that is provided if you prefer...
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/nsnotificationcenter_Class/Reference/Reference.html
Basic Code Example:
#implementation ExampleViewController
//...
- (void)viewDidLoad
{
[super viewDidLoad:animated];
[TCPClass subscribeObserver:self];
}
- (void)viewDidUnload
{
[super viewDidUnload:animated];
[TCPClass unsubscribeObserver:self];
}
- (void)notifySuccess:(NSString*)input
{
//Do whatever I needed to do on success
}
//...
#end
#implementation TCPClass
//...
//Call this function when your TCP class gets its callback saying its done
- (void)notifySuccess:(NSString*)input
{
for( id<Observer> observer in [NSMutableArray arrayWithArray:observerList] )
{
[(NSObject*)observer performSelectorOnMainThread:#selector(notifySuccess:) withObject:input waitUntilDone:YES];
}
}
//maintain a list of classes that observe this one
- (void)subscribeObserver:(id<Observer>)input {
#synchronized(observerList)
{
if ([observerList indexOfObject:input] == NSNotFound) {
[observerList addObject:input];
}
}
}
- (void)unsubscribeObserver:(id<Observer>)input {
#synchronized(observerList)
{
[observerList removeObject:input];
}
}
//...
#end
//Observer.h
//all observers must inherit this interface
#protocol Observer
- (void)notifySuccess:(NSString*)input;
#end
Hope that helps!

Obj-C Private Method Compiler Warnings

Private methods are a useful construct to keep code organised within class boundaries. An example being the organisation of long winded Quartz 2d instructions in a custom UIView subclass. I am able to include such methods in '.m' files with no declaration in '.h'. A working example from a UIView subclass '.m' file reads:
-(void)DoSomethingPrivate { //Not declared in interface
NSLog(#"Does this print a private function?");
}
- (id)initWithFrame:(CGRect)frame //Declared in inherited interface
{
self = [super initWithFrame:frame];
if (self) {
[self DoSomethingPrivate]; //Error: 'Instance method not found'
} //... but it works anyway.
return self;
}
My problem is that the compiler generates the warning "Instance method '-DoSomethingPrivate' not found (return type defaults to 'id')" on the line calling the private function. I'm aware from responses to this question that I can use a 'no name' interface category to 'hide' private method declarations.
However, when I review Apple sample code SimpleStocks, file "SimpleStockView.m", it contains a private function which is neither declared in a no-name category interface, nor does it generate compiler warnings:
//Private Function
- (void)drawRadialGradientInSize:(CGSize)size centeredAt:(CGPoint)center {
...
}
//Is called by this function...
- (UIImage *)patternImageOfSize:(CGSize)size {
...
//The next line doesn't generate any warnings!
[self drawRadialGradientInSize:size centeredAt:center];
...
}
I'd be grateful if anyone can shed any light on how Apple's sample-code private-methods appear to escape compiler checks, so I may avoid having to maintain a 'no-name' category header with all my private methods.
Many thanks.

Calling Cocoa IBAction from Carbon Code

I'm trying to call a Cocoa IBAction from Carbon code...
I've set up global keys using this tutorial.
The hot keys are working fine, but I need to fire an IBAction when the global key has been pressed.
I keep getting errors when I use
[self functionName]
How do I call the function?
I've read about passing the Cocoa controller to the carbon method. How would I do this? or what is the best way?
I assume you're calling [self functionName] in a Carbon Event handler callback. That's not an Objective-C method, so of course self is not defined.
When you install a Carbon Event handler, one of the parameters is a "user data" pointer. You can pass an Objective-C object pointer in this parameter, so that your event handler will get it, and you can say something like [(MyController*) inUserData functionName]. Of course, to make this work, your handler must be in an Objective-C or Objective-C++ source file.
you can pass one of these as your user data while keeping the program safe for c++ translations:
/* include the necessary C header, located in objc/ (objc/objc.h?) */
/* of course, definitions with objc messaging belong in your .mm file */
class t_ibaction_invocation {
/* you may want to retain d_target or d_optionalArgument, and release at destruction */
enum { RetainArguments = 0 };
public:
/* IBAction takes the form: [target action:optionalArgument]; */
t_ibaction_invocation(id target, SEL action, id optionalArgument) : d_target(target), d_action(action), d_optionalArgument(optionalArgument) {
assert(this->d_target);
if (RetainArguments) {
[this->d_target retain];
[this->d_optionalArgument retain];
}
}
~t_ibaction_invocation() {
if (RetainArguments) {
[this->d_target release], target = 0;
[this->d_optionalArgument release], optionalArgument = 0;
}
}
id performAction() {
if (this->d_target && this->d_action) {
return [this->d_target performSelector:this->d_action withObject:this->d_optionalArgument];
}
else {
assert(d_target && d_action);
return 0;
}
}
private:
id d_target;
SEL d_action;
id d_optionalArgument;
};

Methods in super that will be subclassed anyway (Cocoa)

Sorry if this is a repost but I couldn't quite search for it because I can't explain it in a few words. I have a super class with lots of methods but they will always (not all of them) be subclassed. From the super I need to run those methods. I could either leave the methods in super empty or I could just not type them in super but call them anyway like so [self myMethod] and it will call my subclassed method even if it doesn't exist in super. This works but Xcode gives me an error though. 'superclass' may not respond to '-subclassmethod'
What should I do so I won't get the warnings?
I prefer to define the unimplemented methods in the superclass like this:
#interface GLObject : NSObject {}
- (id)someSubclassProvidedMethod;
#end
#implementation GLObject
- (id)someSubclassProvidedMethod {
[self doesNotRecognizeSelector: _cmd];
}
#end
It's almost entirely redundant, because the Objective-C runtime would eventually call -doesNotRecognizeSelector: if I didn't define the method at all. But because I do define it, it's in the class's interface which both keeps the compiler happy and provides me with some documentation.
Rather than the superclass, you could declare the methods in a protocol, what is called a "interface" in other languages.
#protocol MyProtocol
-(id)myMethodWith:(id)arg;
#end
Change the type declaration of the variables to declare that the object conforms to the protocol.
-(id)doStuffWith:(SuperClass <MyProtocol> *)aThing and:(id)another {
return [aThing myMethodWith:another]
}
Note that you won't be able to pass an instance of your SuperClass to doStuffWith:and:, since it won't implement MyProtocol, but it sounds like that's what you want.
My solution was a little weird, but here it is:
#protocol JSDog <NSObject>
- (void)yipe;
#end
#interface JSDog : NSObject
#end
#implementation JSDog
+ (void)initialize {
if ([self isSubclassOfClass:[JSDog class]] && ![self conformsToProtocol:#protocol(JSDog)]) {
NSAssert(false, #"Subclasses of JSDog must conform to <JSDog>.");
}
}
#end
Having a protocol with the same name as a class is precedented in NSObject. Because methods in a formal protocol a by default #required, you will be protected on both ends: in compile-time, if your JSDog subclass purports to conform to <JSDog>, but doesn't implement -yipe, you will receive an error; at runtime, if your subclass does not claim to conform with <JSDog>, you will receive a warning when the subclass is instantiated.
I lately like using NSAssert for this task:
- (BOOL)proceedForVersion:(int)versionInteger
{
NSAssert(false, #"This method needs to be overridden in a subclass of iMBApertureAbstractParser");
return NO;
}

Resources