Expected expression before 'unsigned' ->Objective C - objective-c

m_cAppIdMap is an object of a dictionary.
I want to iterate through the dictionary and to ind and remove the value pEvent.wTimerId is an unsigned short integer that is stored as key in the dictionary.
if(unsigned short* key in m_cAppIdMap) //error:Expected expression before 'unsigned'
{
(void)[self findAndRemoveEvent:pEvent];
(void)CFDictionaryRemoveValue(m_cAppIdMap,&wTimerId);
free(pEvent);
bReturn = YES;
}
I am getting an error when i try to iterate through the loop.
EDITED
-(BOOL)KillTimer:(unsigned short)wTimerId
{
stRs232Timer* pEvent;
BOOL bReturn=FALSE;
theLock = [[NSLock alloc]init];
if ([theLock tryLock]) {
// if ( m_cAppIdMap.Lookup(wTimerId,pEvent) )
// {
// (void)findAndRemoveEvent(pEvent); // remove from event queue
// (void)m_cAppIdMap.RemoveKey(wTimerId); // remove from app map
for(wTimerId in m_cAppIdMap)
{
(void)[self findAndRemoveEvent:pEvent];
(void)CFDictionaryRemoveValue(m_cAppIdMap,&wTimerId);
free(pEvent);
bReturn = YES;
}
[theLock unlock];
}
return bReturn;
}
I am getting error in this code 'selector element does not have a valid object type' . I need to search for wTimerId(key) in the m_cAppIdMap. Is it what i'm doing is correct.The commented lines above the for loop is the implementation of the same code in cpp. I coud not make the same logic over here in Objective C.

I think you meant to use for rather than if. Additionally, the fast enumeration syntax
for (x in y) can only be used on objects that implement the NSFastEnumeration protocol—typically NSArray. It looks like you're using C arrays, so this syntax won't work anyway.

you meant to write for (VARIABLE in CONTAINER) {...} -- but your sample uses if, not for.
side note: it is an error to mutate the collections you iterate over during the iteration.

Related

Ambiguous use of intValue Swift3

I have been trying to convert existing swift2.3 to swift3. I got Ambiguous use on intValue error at the following code.
jobPackageVersion.intJobPackageId = (JobPackageVersionDictionary["intJobPackageId"]! as AnyObject).intValue as NSNumber
Here is the full code
if let url = Bundle.main.url(forResource: "tblJobPackageVersion", withExtension: "csv") {
do {
let strData = try String(contentsOf: url)
let csv = CSwiftV(String: strData)
if csv.keyedRows != nil {
for dictionary in csv.keyedRows! { // [Dictionary<String, String>]
let JobPackageVersionDictionary = dictionary as NSDictionary // Cast to NSDictionary
let JobPackageVersionEntity = NSEntityDescription.entity(forEntityName: "JobPackageVersion", in: context)
let jobPackageVersion = JobPackageVersion(entity: JobPackageVersionEntity!, insertInto: context)
// Set object attributes
jobPackageVersion.intJobPackageId = (JobPackageVersionDictionary["intJobPackageId"]! as AnyObject).intValue as NSNumber
jobPackageVersion.intJobPackageVersionId = (JobPackageVersionDictionary["intJobPackageVersionId"]! as AnyObject).intValue as NSNumber
jobPackageVersion.intStatus = (JobPackageVersionDictionary["intStatus"]! as AnyObject).intValue as NSNumber
jobPackageVersion.intVersion = (JobPackageVersionDictionary["intVersion"]! as AnyObject).intValue as NSNumber
do { // Save object to database and clean up memory
try context.save()
context.refresh(jobPackageVersion, mergeChanges: false)
} catch let error as NSError { Logger.sharedInstance.logMessage("\(#function) JobPackageVersion Saving Error: \(error.userInfo)") }
} // for-loop
Logger.sharedInstance.logMessage("\(#function): Loaded \(csv.keyedRows!.count) tblJobPackageVersion records.")
} else { Logger.sharedInstance.logMessage("\(#function) CSV Parser Warning: no CSV data was parsed in tblJobPackageVersion.csv!") }
} catch { Logger.sharedInstance.logMessage("\(#function) Error reading contents of tblJobPackageVersion.csv.") }
} else { Logger.sharedInstance.logMessage("\(#function) Error locating URL for resource tblJobPackageVersion.csv") }
}
Any help would be appreciated.
Thanks.
You're trying to call intValue on an object of type AnyObject. As the error states, this is too ambiguous because both NSNumber and NSString have intValue properties. Xcode doesn't know which intValue to use, because both NSNumber and NSString fall under the AnyObject umbrella. Since Xcode is confused, you need to be more specific about what type your object is. Try something like this:
jobPackageVersion.intJobPackageId = (JobPackageVersionDictionary["intJobPackageId"]! as NSNumber).intValue
Note 1: You're probably going to get the same error with the other objects you call intValue on, but you can fix them accordingly.
Note 2: Be extremely careful about force unwrapping your objects using !. If the dictionary you're using ever returns nil your program will crash. Instead I would safely unwrap them using either an if let or guard statement depending on your use case. Something like this may work a little better:
guard let intJobPackageId = JobPackageVersionDictionary["intJobPackageId"] as? NSNumber,
let intJobPackageVersionId = JobPackageVersionDictionary["intJobPackageVersionId"] as? NSNumber,
let intStatus = JobPackageVersionDictionary["intStatus"] as? NSNumber,
let intVersion = JobPackageVersionDictionary["intVersion"] as? NSNumber
else {
print("one of the dictionary values is nil")
return
}
jobPackageVersion.intJobPackageId = intJobPackageId.intValue
jobPackageVersion.intJobPackageVersionId = intJobPackageVersionId.intValue
jobPackageVersion.intStatus = intStatus.intValue
jobPackageVersion.intVersion = intVersion.intValue
This may not be exactly what you want, but it should give you an idea on how to safely unwrap your objects so your app doesn't crash. You can play around with it and decide what's best for you.

Objective C: Using a BOOL to return 'YES' if a condition can be applied

Hi there I have some code at the moment that gives me the error ("0") is not equal to ("50") - condition not applied correctly Basically I am currently using a traditional for loop within a BOOL which goes through the list of items and checks whether or not the condition can be applied, if it can be applied to an item then the BOOL will return YES. I cannot see where I am currently going wrong and need guidance. My code is shown below:
-(BOOL)conditionCanBeApplied:(NSArray *)items{
bool itemConditionCanBeApplied = NO;
for (int i = 0; i < items.count; i++)
{
id myItem = [[items valueForKeyPath:#"itemId"]objectAtIndex: i];
if ([self.applicableItems containsObject:myItem]) {
itemConditionCanBeApplied = YES;
}
}
return itemConditionCanBeApplied;
}
First, don't mix BOOL and bool, they might be very similar but they aren't the same data type. Second, always use fast enumeration if you have a choice. I am assuming in the code below that your items collection is something like an NSArray. Also, there is no reason to test with an if statement just to set a BOOL since the test is a boolean statement. (I am doing it in my example to allow for the break) Lastly, short-circuiting your logic with a break keeps the processor from doing unnecessary work once you have at least one match.
Do something like this:
- (BOOL)conditionTest
{
BOOL itemConditionCanBeApplied = NO;
for (id item in items) {
if ([self.applicableItems containsObject:item]) {
itemConditionCanBeApplied = YES;
break;
}
}
return itemConditionCanBeApplied;
}

A function that can return an object or a primitive type: is it possible?

NOTE: the beginning of this question is similar (the first part is the same) as this one: LINK
However, the final question is completely different.
I'm implementing a "Code Injector Class", that through method swizzling can give you the possibility to do something like this:
FLCodeInjector *injector = [FLCodeInjector injectorForClass:[self class]];
[injector injectCodeBeforeSelector:#selector(aSelector:) code:^{
NSLog(#"This code should be injected");
}];
aSelector can be a method with variable number of arguments, and variable return type. Arguments / and return type can be objects or primitive type.
First, I attach the code of injectCodeBeforeSelector: to let you understand what I'm doing (I removed not interesting parts of the code):
- (void)injectCodeBeforeSelector:(SEL)method code:(void (^)())completionBlock
{
NSString *selector = NSStringFromSelector(method);
[self.dictionaryOfBlocks setObject:completionBlock forKey:selector];
NSString *swizzleSelector = [NSString stringWithFormat:#"SWZ%#", selector];
//NSMethodSignature *signature = [self.mainClass instanceMethodSignatureForSelector:method];
// add a new method to the swizzled class
Method origMethod = class_getInstanceMethod(self.mainClass, NSSelectorFromString(selector));
const char *encoding = method_getTypeEncoding(origMethod);
[self addSelector:NSSelectorFromString(swizzleSelector) toClass:self.mainClass originalSelector:method methodTypeEncoding:encoding];
SwizzleMe(self.mainClass, NSSelectorFromString(selector), NSSelectorFromString(swizzleSelector));
}
-(void)addSelector:(SEL)selector toClass:(Class)aClass originalSelector:(SEL)originalSel methodTypeEncoding:(const char *)encoding
{
//NSMethodSignature *signature = [aClass methodSignatureForSelector:originalSel];
NSMethodSignature *signature = [NSMethodSignature signatureWithObjCTypes:encoding];
const char *type = [signature methodReturnType];
IMP implementation = (IMP)intGenericFunction;
if (strcmp(#encode(id), type) == 0) {
// the argument is an object
implementation = objectGenericFunction;
}
else if (strcmp(#encode(int), type) == 0)
{
// the argument is an int
implementation = (IMP)intGenericFunction;
}
else if (strcmp(#encode(long), type) == 0)
{
// the argument is a long
implementation = (IMP)longGenericFunction;
}
else if (strcmp(#encode(double), type) == 0)
{
// the argument is double
implementation = (IMP)doubleGenericFunction;
}
else if (strcmp(#encode(float), type) == 0)
{
// the argument is float
implementation = (IMP)floatGenericFunction;
}
else
{
// the argument is char or others
implementation = (IMP)intGenericFunction;
}
class_addMethod(aClass,
selector,
implementation, encoding);
}
What is happening here? Basically, basing on the expected return type of the original selector, I add a new method to the object with the correct return type, then apply the swizzle.
All is working correctly, but I'd like to know if it's possible to "compact" the following code (some syntax that I don't know or something I'm missing), because for each return type I have a function that is almost identical to the others, only the returned type is different.
I attach two of them as an example:
int intGenericFunction(id self, SEL cmd, ...) {
FLCodeInjector *injector = [FLCodeInjector injectorForClass:[self class]];
[injector executeBlockForSelector:cmd];
va_list arguments, copiedArguments;
va_start ( arguments, cmd );
va_copy(copiedArguments, arguments);
va_end(arguments);
void * returnValue = getReturnValue(self, cmd, copiedArguments);
int returnedInt = *(int *)returnValue;
return returnedInt;
}
double doubleGenericFunction(id self, SEL cmd, ...) {
FLCodeInjector *injector = [FLCodeInjector injectorForClass:[self class]];
[injector executeBlockForSelector:cmd];
va_list arguments, copiedArguments;
va_start ( arguments, cmd );
va_copy(copiedArguments, arguments);
va_end(arguments);
void * returnValue = getReturnValue(self, cmd, copiedArguments);
double returnedDouble = *(double *)returnValue;
return returnedDouble;
}
As you can see, the functions are almost identical, the only different is the CAST before the return, and the return type of the function.
I'm implementing it in the correct way, or there are more efficient way to do it?
Thanks
You're correct that you'll need to write a different IMP for each return type, at least unless you drop down to assembly to do the dispatch, the way objc_msgSend does. (Even that function requires a couple different type variants, though.) However, if the difference truly is just a couple of type names, you may be able to define a macro that reduces the boilerplate:
// This macro syntax is off the top of my head; it may not be correct.
#define GENERIC_FUNCTION_FOR_TYPE(type) type type##GenericFunction(id self, SEL cmd, ...) { \
...other lines omitted... \
type returnedValue = *(type *)returnValue; \
return returnedValue; \
}
GENERIC_FUNCTION_FOR_TYPE(int)
GENERIC_FUNCTION_FOR_TYPE(double)
...etc...

Can an If Statement tell if an assignment was valid?

I have an object that returns a value if successful and false (or nil) if it failed.
i want to assign that value to a variable
if(var1 = [object foo])
{
//if the [object foo] returned a variable, goes here
}
else
{
//[object foo] returned FALSE (or nil), go here
}
can an If statement detected if an assignment was valid?
This is all right but will generate a warning, since this is a common typo (= instead of ==). To silence that warning add another set of parentheses like this:
if ((var = [object foo])) ...
Since this easily can lead to misunderstandings a lot of people will advise against doing this. For a simple if statement this is much clearer to do the assignment first:
var = [object for];
if (var) ...
In while loops this is more useful, but also considered harmful by many people.
Not sure I understand your question, but let me try and explain a few situations you can check
1) Property contains value
if ([object foo])
{
// If foo has a value associated to it that is not nil/false/zero
}
else
{
// If foo equals nil, false or zero
}
2) Assignment to a variable was successful
if ((bar = [object myMethod]))
{
// If myMethod returns any non-nil value
}
else
{
// If myMethod returns nil
}
3) Previous assignment of a variable was successful
bar = [object myMethod];
if (bar)
{
// If bar has a value associated to it that is not nil/false/zero
}
else
{
// If bar equals nil, false or zero
}
use == instead of = in the if statement.
before the if statement, you may have var1 = [object foo]
see comparison operators
If you mean by valid that the variable contains an expected result, you can just perform another if on the variable against the expected result, or null to check it.

How to return a C-array from method in Objective-C?

I have a function that returns a variable and I want to know how to return an array the issue is it isn't an NSArray it is just an average C array like this...
-(b2Fixture*) addFixturesToBody:(b2Body*)body forShapeName:(NSString*)shape
{
BodyDef *so = [shapeObjects objectForKey:shape];
assert(so);
FixtureDef *fix = so->fixtures;
int count = -1;
b2Fixture *Fixi[4];
while(fix)
{
count++;
NSLog(#"count = %d",count);
Fixi[count]= body->CreateFixture(&fix->fixture);
if (Fixi[count]!=0) {
NSLog(#"Fixi %d is not 0",count);
}
if (body->CreateFixture(&fix->fixture)!=0) {
NSLog(#"body %d is not 0",count);
}
fix = fix->next;
}
return *Fixi;
}
If you see some variable types you don't know it's because I'm using cocos2d framework to make a game but I'm returning a variable of b2Fixture... This code compiles however only saves the value of the first block of the array "fixi[0]" not the whole array like I want to pass
anyhelp :) thankyou
You can't return a local array. You'll need to do some kind of dynamic allocation or pull a trick like having the array inside a structure.
Here is a link to an in-depth article that should help you out.
In general returning C arrays by value is a bad idea, as arrays can be very large. Objective-C arrays are by-reference types - they are dynamically allocated and a reference, which is small, is what is passed around. You can dynamically allocate C arrays as well, using one of the malloc family for allocation and free for deallocation.
You can pass C structures around by value, and this is common, as in general structures tend to be small (or smallish anyway).
Now in your case you are using a small array, it has just 4 elements. If you consider passing these 4 values around by value is reasonable and a good fit for your design then you can do so simply by embedding the C array in a C structure:
typedef struct
{
b2Fixture *elements[4];
} b2FixtureArray;
...
-(b2FixtureArray) addFixturesToBody:(b2Body*)body forShapeName:(NSString*)shape
{
BodyDef *so = [shapeObjects objectForKey:shape];
assert(so);
FixtureDef *fix = so->fixtures;
int count = -1;
b2FixtureArray Fixi;
while(fix)
{
count++;
NSLog(#"count = %d", count);
Fixi.elements[count]= body->CreateFixture(&fix->fixture);
if (Fixi.elements[count] != 0)
{
NSLog(#"Fixi %d is not 0",count);
}
if (body->CreateFixture(&fix->fixture) != 0)
{
NSLog(#"body %d is not 0", count);
}
fix = fix->next;
}
return Fixi;
}
...
// sample call outline
b2FixtureArray result = [self addFixturesToBody...]
Whether this standard C "trick" for passing arrays by value is appropriate for your case you'll have to decide.
Note: If b2fixture is an Objective-C object make sure you understand the memory management implications of having a C array of objects references depending on the memory management model (MRC, ARC, GC) you are using.
If you need to design function or method that has to return a fixed or limited size array, one possibility is to pass a pointer to the result array to the function or method as a parameter. Then the caller can take care of allocating space, or just use a local or instance variable array. You might want the called function to sanity check that the array parameter isn't NULL before using the array.