So I have a class called Routes in which I have a function called getRouteInfo() that takes no parameters and has no return value and it is inside a Cocoa Touch class file. Then I have a tableView controller in which I want to call this function inside the viewDidLoad() method. For some reason, the compiler is forcing me to pass a parameter into it of type Routes even though my function is meant to not take any parameters.
The compiler is forcing me to pass a parameter inside the function :
Now, when I tried passing nil to it, I get the following error message: Nil is not compatible with expected argument type Routes.
Then when I try simply calling it as Routes.getRouteInfo() the compiler yells at me with: Missing argument for parameter #1 in call
If anybody could tell me why this is happening and how to resolve it, I'll be extremely grateful.
Related
I'm currently working on a library, and ran into some strange inconsistencies in behaviour between my unit test code, and an actual app I'm basing on the code.
See, I'm trying to get a Type struct from the name of the class I want to instantiate, but I get nothing (e.g. Type is there, but name() produces null, is_a() fails, etc.)
However, if I make an instance of the type first, then try to get the Type based on name once more, it works just as I expected (which is probably why my unit tests work)
So I was wondering, when is a type registered by the type system and available via. from_name(...) ?
Does the type system only know it after it has been instantiated at run time? Is there another reason a class name wouldn't be recognized until an instance of the class has been instantiated? Should I use some other method of registration?
I'm coding in Vala if that makes any kind of a difference.
A type is first registered with the type system when its get_type() function is called. This is called in a number of places, basically whenever you need to get the GType for that type. Typically, it will first be called during class_init of the type, which happens during the first instance init.
So essentially you are right when you say “does the type system only know it after it has been instantiated at run time”, because that’s normally what happens. However, you can bring type registration forward by explicitly calling the get_type() function for a type early, and passing it to g_type_ensure(). For example, see what GLib does here:
/* Initialize types from built-in "modules" */
g_type_ensure (g_null_settings_backend_get_type ());
g_type_ensure (g_memory_settings_backend_get_type ());
g_type_ensure (g_keyfile_settings_backend_get_type ());
…
I am using DDLogFormatter to format message and add there fileName, function and line to my logging but I don't call CocoaLumberjack directly , instead delegating so I can do some syntactic improvements. But now when I implemented it I realized I am getting wrong information in formatter, not actually wrong it's correct but I want to know one step before in stack to put it in log statement so I get fileName, function and line where actually calling happened to my delegating method.
I found workaround as #function, #file, #line for swift... for obj-c calls I will omit this info for now.
I am using OCMock 3 to do unit testing in my iOS project.
I simply want to verify that a function is invoked without concerning what is the argument value passed in.
For example, I want to verify the following function is invoked:
[school startTime:currentTime];
(Short note: the funcition in School class -(void)startTime:(long long) takes a long long type parameter)
In my test case I tried:
OCMVerify([schoolMock startTime:(long long)[OCMArg any]]);
I am pretty sure the code under test has been invoked, but I get error:
OCMockObject(School):Method startTime:2005634354 was not invoked.
It looks like OCMock is still verifying the exact value of argument passed into the function. WHY?
Your cast from [OCMArg any] to a type (long long) is converts the OCMock object to the value 2005634354, which is why the test expects that as the parameter. startTime is expecting a non-object argument, which is not supported for [OCMArg any]. If you remove the cast to long long you would probably get a compiler warning.
Instead, change your verification to this:
OCMVerify([[schoolMock ignoringNonObjectArgs] startTime:0]);
ignoringNonObjectArgs will do just as the name implies: the non-object argument expected by startTime will be entirely ignored. I usually use 0 to have a consistent and not confusing placeholder value, but in theory you could put any long long you want in the verify, and as long as the method is called by your mock object this will pass.
The OCMock documentation is pretty clear about this, I think: "Arguments that are neither objects nor pointers or selectors cannot be ignored using an any placeholder." (Section 4.1).
I'm trying to setup a mock function that will return a value which is based on the input. The only way to access the input parameter that I know of is via the WillExecute method. However, you have to specify a When clause, and that When clause expects me to define an input value along with the method, in the following fashion:
aMock.Setup.WillExecute(function ...).When.myFunc(1);
I'm kinda forced to say: call that anonymous function, whenever myFunc(1) is called. I'd like to be able to do the same, but on every possible parameter to myFunc, with a kind of wildcard marker in the parameter to myFunc (conceptually):
aMock.Setup.WillExecute(function ...).When.myFunc(*);
Is something like this possible? Basically a When clause that will match any value passed as parameter.
Someone might be tempted to point out the WillReturnDefault value, but method does not have access to the actual parameters of the call, as WillExecute does, so I won't be able to setup anything but a constant value.
Thanks.
Ok, I missed the fact that there was an overloaded version of WillExecute that will do exactly that:
//Will exedute the func when called with the specified parameters
function WillExecute(const func : TExecuteFunc) : IWhen<T>;overload;
//will always execute the func no matter what parameters are specified.
procedure WillExecute(const AMethodName : string; const func : TExecuteFunc);overload;
This way I can tell the mock to execute the passed anon whenever the method is called, regardless of its parameters, while still providing access to them. Exactly what I was looking for. Closing question. Thanks.
This can also be solved by using parameter matching:
aMock.Setup.WillExecute(function ...).When.myFunc(It0.IsAny<Integer>);
Lets say I have a sample class helper
TSampleClassHelper = class helper for TSampleClass
public
procedure SomeHelper;
end;
I do the following:
var
obj :TSampleClass;
begin
obj:=TSampleClass.Create;
obj.SomeHelper;
end;
and this works as expected.
But how can I use RTTI to invoke the helper method instead? The following does not seem to work, GetMethod returns nil.
var
obj :TSampleClass;
ctx :TRTTIContext;
rtype :TRTTIType;
rmethod :TRTTIMethod;
begin
obj:=TSampleClass.Create;
rtype:=ctx.GetType(obj.ClassType);
rmethod:=rtype.GetMethod('SomeHelper'); // rmethod is nil !
end;
So does RTTI not work for methods defined in class helpers? Is there anyway around this?
Thanks.
The reason your code returns a nil method is that the object's type does not contain a method named SomeHelper. The type that contains that method is the helper type.
So, you could write this which will return a non-nil method:
obj:=TSampleClass.Create;
rtype:=ctx.GetType(TypeInfo(TSampleClassHelper));
rmethod:=rtype.GetMethod('SomeHelper');
Of course, you should immediately see the first problem, namely the use of a compile time specified type, TSampleClassHelper. Can we use RTTI to discover TSampleClassHelper at run time based on the type of the instance? No we cannot, as I will explain below.
Even if we put that to one side, as far as I can see, there's no way to invoke the method using RTTI. If you call rmethod.Invoke(obj, []) then the code in TRttiInstanceMethodEx.DispatchInvoke blocks an attempt to call the helper method. It blocks it because it decrees that the type of the instance is not compatible with the class of the method. The pertinent code is:
if (cls <> nil) and not cls.InheritsFrom(TRttiInstanceType(Parent).MetaclassType) then
raise EInvalidCast.CreateRes(#SInvalidCast);
Well, you can obtain the code address of the helper method with rmethod.CodeAddress but you'll need to find some other way to invoke that method. It's easy enough to cast it to a method with the appropriate signature and invoke it. But why bother with rmethod.CodeAddress in any case? Why not use TSomeHelperClass.SomeMethod and cut RTTI out of the loop?
Discussion
Helper resolution is performed statically based on the active helper at the point of compilation. Once you attempt to invoke a helper method using RTTI there is no active helper. You've long since finished compiling. So you have to decide which helper class to use. At which point, you don't need RTTI.
The fundamental issue here is that class helper method resolution is fundamentally a static process performed using the context of the compiler. Since there is not compiler context at run time, class helper method resolution cannot be performed using RTTI.
For more insight into this have a read of Allen Bauer's answer here: Find all Class Helpers in Delphi at runtime using RTTI?