Taking the below method as an example:
-(void)myMethodName:(int)xCoordinate yCoordinate:(int)yCoordinate
When I write the method in my code [self etc...], Xcode does its auto complete which tells me what the second value is for but never the first (see pic).
Is there any way I can also include the 'description' for the first value of a method?
This is just a matter of how you name your method. It autocompletes the entire method name. If the method name is descriptive of its parameters, then you'll see it in the autocomplete.
Are you trying to get something like this?
-(void)myMethodNameWithXCoordinate:(int)xCoordinate yCoordinate:(int)yCoordinate
This is how the methods are usually defined in objective C
- (int)addX:(int)x toY:(int)y {
int sum = x + y;
return sum;
}
Like others have said rename your method this way and it will make things clearer
-(void)moveStuffFromXCoordinate:(int)xCoordinate toYCoordinate:(int)yCoordinate
Based on the Apple Documentation on coding guidelines for cocoa when naming methods with parameters the word before the argument should describe the argument.
Make the word before the argument describe the argument.
Right - (id)viewWithTag:(NSInteger)aTag;
The above is right because it describes the argument as a Tag where as the below doesn't describe the argument as anything.
Wrong - (id)taggedView:(int)aTag;
So in your case
Wrong -(void)myMethodName:(int)xCoordinate yCoordinate:(int)yCoordinate;
it should be
Right -(void)myMethodNameForXCoordinates:(int)xCoordinate andYCoordinate:(int)yCoordinate;
Related
i'm starting with Swift by developing a simple application with a tableView, a request to a server and a few things more. I realized that every method inside UITableViewDelegate protocol is named in the same way (i guess it might be the same with other protocols) and the differences are made by changing the parameters passed to those methods (which are called "tableView" by the way).
I was wondering why Apple would do something like this, as it's a bit messy when i try to implement method from this protocol, as i can't start typing "didSele..." just to autocomplete with "didSelectRowAtIndexPath"; instead i have to type "tableView" to get a list of all available methods and manually search for the one whose second parameter is "didSelectRowAtIndexPath".
Everything's working fine, but just trying to know WHY could this be done this way.
Thank you so much in advice :)
PS: There's a screenshot about what i'm saying:
Swift is designed to be compatible with Objective-C. After all, almost all existing OS X and iOS APIs are in Objective-C and C (with a bit of C++ code here and there). Swift needs to be able to use those APIs and thus support most Objective-C features one way or the other. One of the most important features of Objective-C is how method calls are made.
For example, in C, a function with 3 arguments is called like this:
foo(1, "bar", 3);
You don't know what the arguments are supposed to be. So in Objective-C, the arguments are interleaved with the method name. For example, a method's name might be fooWithNumber:someString:anotherNumber: and it would be called like:
[anObject fooWithNumber:1 someString:#"bar" anotherNumber:3];
Swift now tries to be compatible with this Objective-C feature. It thus supports a form of named arguments. The call in Swift would look like:
anObject.foo(number:1, someString:#"bar", anotherNumber:3)
Often Swift method definitions are written so that you don't need to explicitly name the first argument, like:
anObject.foo(1, someString:#"bar", anotherNumber:3)
If you look up the UITableViewDelegate protocol documentation and select Objective-C you can see that all of these methods start with tableView: to designate the sender, but from then on they are very different. The list you've cited is the result of the conversion from Objective-C to Swift naming convention.
It is just naming conventions. It is the same in Objective-C. You can have a look to this page. Without these conventions it would be a complete mess.
The method name is not only the first word but also the public names of the parameters.
E.g. it the method name is not tableView() but tableView(_:didSelectRowAtIndexPath:).
an Objective-C method has params, and each param except the first one has two names:call name and var name, for example:
-SomeMessage:(type)varName callName2:(type)varName2
so, what's the use of callName ? why we need two names for an param?
Let's have a better method example:
- dataForKey:(NSString *)key withEncoding:(NSString *)encoding;
The first name, how you call it, is actually part of the method name, the whole method name is:
- dataForKey:withEncoding:
(including the colons).
Obj-C prefers method names that can be read like sentences. This is useful in context of the caller. In languages like Java or C++ the method would be called like this
data = object.getData("key", "ASCII")
which is difficult to understand for the readers because they doesn't know what the parameters stand for. In Obj-C
data = [object dataForKey:#"key" withEncoding:#"ASCII"];
is easy to understand without looking at the method declaration.
Its to make your code more readable, each "call name" is a description of a parameter
so instead of C style having myMethod(5, 4, 9, 2)
you would have [self myMethodWithParam:5 andACoolNumber:4 thisShouldBeNine:9 divisor:2];
which just helps you understand what the functions parameters need to be, its optional, but you should always do it to help with code maintainability
This is how it works what you wrote is correct "Somemessage" and "callName2" are part of the method name while varName and varName2 are variables .
callname2 is optional , generally it is used if we want to give any definition for the variable we writes after that
Hope this helped you.
i want to build a small plugin-system for objects in objective-c.
Now i am stuck at the point where i want to dynamically (at runtime) add a line of code to every function available in an object.
I have played around with the runtime library but came to no solution, yet.
What i have tried so far is this:
id (^impyBlock)(id, id, ... ) = ^(id self_, id arguments, ...)
{
// My custom code for every function here
id (*func)(__strong id,SEL,...) = (id (*)(__strong id, SEL, ...))imp;
return func(obj, s, arguments);
};
id (*impyFunct)(id, SEL,...) = imp_implementationWithBlock(impyBlock);
method_setImplementation(mList[i], impyFunct);
My problem is, when there is more than one argument i got no chance to pass them to "func()". AFAIK this is not possible in C.
Another solution i have thought about is doing some magic with method swizzling.
In steps:
Create a "swizzle Method" which just calls my custom code and calls the original method afterwards (by a naming schema)
Change the IMP of every function with the one of the "swizzle Method"
Create a new method with the "old" implementation and change to name to a schema like "___name"
In this solution i am stuck at point 3. I haven't managed to dynamically create a complete new method.
Does anybody can help me with my problems above or has another solution for a "catch all method functionality".
The best would be something like forwardInvocation which also catches already defined functions.
Thanks for your help!
Lemme break this into two parts since I just can't get the connection between your two questions.
I. Create a new method with the "old" implementation and change to name to a schema like "___name"
That's fairly easy, although I don't understand how that would be able to solve your problem. You still can't pass down variadic function arguments to such a method (and you're right, that can't be done in C).
IMP swapImpForSelector(Class cls, SEL sel, IMP newImp)
{
Method m = class_getInstanceMethod(cls, sel);
IMP oldImp = method_setImplementation(m, newImp);
NSString *newSel = [NSString stringWithFormat:#"__prefixed_%#", NSStringFromSelector(sel)];
const char *type = method_getTypeEncoding(m);
class_addMethod(cls, NSSelectorFromString(newSel), oldImp, type);
return oldImp;
}
II. If you want to pass variadic arguments between functions, you may need to fall back to heavy assembly hackage. Fortunately, some smart people have already done that for you.
Either use the NSInvocation class, or if it isn't sufficient, then libffi is even lower-level.
Doing this for arbitrary objects will be quite hard. Take a look at AspectCocoa for something along these lines, but you'll see it doesn't work so great and isn't recommended for use in a production environment.
But for a plugin system, you'd be better off just defining something like a PluggableObject class that is designed with extension in mind. Forget about running arbitrary blocks in the middle of arbitrary methods — instead, define specific "sockets" where things can plug in and an interface that those things can follow to get the functionality you want to support. It'll be a lot more stable and easier to add and fix things.
I've found properties corresponding to each action named like this: MVC.<Controller>.<Action>Params, they contain parameter names for each action. What are they for and how they can be used?
There were some edge scenarios where it was interesting to pass the parameter name as a constant. I can't instantly recall what that person was doing, but I could see this being useful is calls to AddRouteValue. In the end, it's all about never to have to use a literal string that refers to a C# object, whether it's a class, method, or param.
This is similar to the question asked at StructureMap - Override constructor arguments for a named instance, but different in the respect that I don't know the type at coding time and therefore cannot use the generic form of GetInstance().
So while:
ObjectFactory.With(IFoo).GetInstance<IBar>("foobar");
will work, there is apparently no way to call:
ObjectFactory.With(IFoo).GetInstance(typeof(IBar), "foobar");
I have a workaround using a private generic method and the MakeGenericMethod() on that private method's MethodInfo.
As you might imagine, I'm not really happy with that approach, but I cannot see any other way out of the situation.
The method you want is GetNamedInstance(), which is not available when you use the With() method. I'm sure it would not be too hard to add it, maybe you could email Jeremy Miller and see if he can add it in StructureMap 3. Or submit a patch :)