what's the purpose of parameter ‘data’ in SDCacheQueryCompletedBlock - nsdata

typedef void(^SDCacheQueryCompletedBlock)(UIImage * _Nullable image, NSData * _Nullable data, SDImageCacheType cacheType);
what's the purpose of the second parameter 'data' since I can not find anywhere using it?

According to the ChangeLog:
For #1575 GIF support using FLAnimatedImage, several changes were needed:
• replaced type SDWebImageQueryCompletedBlock with SDCacheQueryCompletedBlock and added an NSData * param
• because of the change above, the done param of SDImageCache queryDiskCacheForKey:done: is now a SDCacheQueryCompletedBlock and those blocks must now include an NSData * param
• replaced type SDWebImageCompletionWithFinishedBlock with SDInternalCompletionBlock and added an NSData * param
• because of the change above, the completed param of SDWebImageManager loadImageWithURL:options:progress:completed: is now SDInternalCompletionBlock and those blocks must now include an NSData * param
• for consistency with the previous change, also renamed SDWebImageCompletionBlock to SDExternalCompletionBlock
• UIImage will no longer respond to sd_animatedGIFNamed: or sd_animatedImageByScalingAndCroppingToSize:
tl;dr:
Change because of FLAnimatedImage.

Related

Understanding NiFpga_MergeStatus() function with a hard-coded value as a parameter

I am picking up on someone else's code (which works and is currently being used in hardware applications). The given code is implemented in Qt since we need to produce an application, and creates an application which allows the user to set certain parameters using a gui while the code handles transferring this command through a NI PXI to the FPGAs etc.
On my way of understanding this code, I found a function call to NiFpga_MergeStatus() shown in the code below. The parameter passed as the first argument has been hardcoded and set to NiFpga_Status_Success (which if you follow the path is a static const NiFpga_Status type set to the the value 0.
When looking at the NiFpga_MergeStatus() function implementation, I believe with this value being hardcoded, we will never get to the second if statement and our return value will be the Invalid Parameter value.
Why would somebody want to implement such code? Especially since the second parameter is sent it seems to have had some thought put into this. Am I wrong in analyzing that with harcoding the status parameter before it's passed as an argument we will always execute the first if statement? Let me know if I should provide more details. The header file is provided by Ni (NiFpga.h).
Thank you
NiFpga description of this function's purpose:
* Conditionally sets the status to a new value. The previous status is
* preserved unless the new status is more of an error, which means that
* warnings and errors overwrite successes, and errors overwrite warnings. New
* errors do not overwrite older errors, and new warnings do not overwrite
* older warnings.
*
* #param status status to conditionally set
* #param newStatus new status value that may be set
* #return the resulting status
static NiFpga_Inline NiFpga_Status NiFpga_MergeStatus(
NiFpga_Status* const status,
const NiFpga_Status newStatus)
{
if (!status) //
return NiFpga_Status_InvalidParameter;
if(NiFpga_IsNotError(*status)
&& (*status == NiFpga_Status_Success || NiFpga_IsError(newStatus)))
*status = newStatus;
return *status;
}
Status is a pointer parameter. In first if statement (if (!status)) it is only checking if the pointer is actually pointing to something in memory or not. So in your case it always evaluates to false and return NiFpga_Status_InvalidParameter; never gets called.
But second if statement is doing the job of comparing actual value (note the asterisk *) of status (*status) with NiFpga_Status_Success.

Avoiding downcasts in a Swift 3 completion handler with Google Drive REST API

I'm using the Google Drive REST API in a Swift 3 app. Queries are executed using the executeQuery method of GTLRDriveService. This method takes a completion block of type GTLRServiceCompletionHandler?, which in turn is declared as
public typealias GTLRServiceCompletionHandler = (GTLRServiceTicket, Any?, Error?) -> Swift.Void
Because of this declaration, the second parameter must be downcast to the appropriate type inside the block. For instance:
let createPermissionQuery = GTLRDriveQuery_PermissionsCreate.query(
withObject: permission, fileId: toShare.id)
...
driveService.executeQuery(createPermissionQuery) { (ticket, result, error) in
if (error == nil) {
// need to downcast result to GTLRDrive_Permission
let permission = result as! GTLRDrive_Permission
...
}
}
The second parameter is always of a specific type that is completely determined by the particular query passed to executeQuery. For instance, if one passes an instance of GTLRDriveQuery_PermissionsCreate, then the second parameter (if the query succeeds) will always be of type GTLRDrive_Permission. However, if I try to declare result to be of any type other than Any?, the code won't compile.
In Objective C, the completion block can be specified with a type that's specific to the query. For instance (adapted from here):
GTLRDriveQuery_PermissionsCreate *createPermissionQuery =
[GTLRDriveQuery_PermissionsCreate queryWithObject:permission
fileId:fileId];
...
[driveService executeQuery:createPermissionQuery
completionHandler:^((GTLRServiceTicket *ticket,
GTLRDrive_Permission *permission,
NSError *error) {
if (error == nil) {
// work directly with permission
...
}
}];
Is there any way to avoid this downcast? (I'm asking out of ignorance; I'm somewhat of a newbie to Swift.) If I was writing my own library, I'd design the method signatures differently, but this is Google's library and am kind of stuck with what they supply. Perhaps some sort of extension or layer on top of Google's code?
You might be able to specify an extension that wraps the Google execute method, takes a generic and casts to your generic type in the block. This would basically just be a pretty abstraction of what you're doing already, but for all types your extension would be designed to cover.

(__bridge__transfer NSData*) returns _NSCFArray instead of NSData

I have some code I am using for keychain management. The SecItemCopyMatching method returns the result in (CFTypeRef *) type called foundDict, which is passed as a reference to the SecItemCopyMatching method. Then I am using (__bridge_transfer NSData*) to bridge from the CFTypeRef* to an NSData* (into "result" variable).
So I was expecting that the result variable will of course be of type NSData, because I declared it so, and used the bridge to convert CFTypeRef* to NSData*.
But when I want to convert the NSData into a string using the NSString method: initWithBytes:length:encoding, I get a runtime error that tells me
"[__NSCFArray bytes]: unrecognized selector set to instance.."
When I looked in the debugger in Xcode , I can see why it is complaining because the "result" variable was converted from NSData to __NSCFArray after the "bridge" statement. And since __NSCFArray is an array type it does not support a method called "bytes" and thus the runtime complains
So, I don't understand why internally this conversion is happening from NSData to __NSCFArray
And most importantly, how is the proper way to convert the results returned by the "SecItemCopyMatching" which is of type CFTypeRef to NSData. The funny thing is that i am following the exact same code suggested by Apple in its keychain wrapper example at KeychainWrapper Sample code
Any thoughts?
I am attaching an image of the debugger:

Changing model parameters by cPar in other module

I am using this module hierarchy :
Node: {udpApp[0]<->udp<->networkLayer->wlan[0]} and wlan[0]: {CNPCBeacon<->mac<->radio}
I have given some initial parameter in the ini file for udpApp as :
**.host*.numUdpApps = 2
**.host*.udpApp[0].typename = "UDPBasicApp"
**.host*.udpApp[0].chooseDestAddrMode = "perBurst"
**.host*.udpApp[0].destAddresses = "gw1"
**.host*.udpApp[0].startTime = 1.32s
**.host*.udpApp[0].stopTime = 1.48s
But at run time I want to change the startTime and stopTime for udpAPP[0] through CNPCBeacon module. Hence I changed CNPCBeacon.cc as:-
cModule* parentmod = getParentModule();
cModule* grantParentmod = parentmod->getParentModule();
cModule* udpmod;
for (cSubModIterator iter(*grantParentmod); !iter.end(); iter++)
{
//EV<<"get the modulde "<< iter()->getFullName()<<endl;
if (strcmp(iter()->getFullName(), "udpApp[0]") == 0)
{
udpmod = iter();
break;
}
}
cPar& startTime = udpmod->par("startTime");
cPar& stopTime = udpmod->par("stopTime");
And I am successfully able to receive the values of startTime and stopTime. However I want to change these value in current module, which is resulting in an error by following code:
udpmod->par("startTime").setDoubleValue(4.2);
Can anybody please suggest me a way to change it at run time.
Declaring your parameter as volatile should solve your problem. But for future reference I'll provide further explanation below
Volatile vs. non-volatile:
Here it depends how you want to use this parameter. Mainly via the .ini file you have two types of parameters: volatile and non-volatile.
volatile parameters are read every time during your run. That woule be helpful if you want this parameter to be generated by a built-in function, for example, uniform(0,10) each time this volatile parameter will get a different value.
On the other hand non-volatile parameters are read just one, as they don't change from run to run.
Using the volatile type parameter does not give you full flexibility, in the sense that your parameter value will always fall with in a range predefined in the .ini
Dynamic Variable (parameter) Reassignment:
Instead what you could do is use a more robust approach, and re-define the variable which stores the value from that module parameter each time you have to do so.
For example in your case you could do the following:
varHoldingStartTime = par("startTime").doubleValue();
varHoldingStartTime = 4.2;
This way the actual value will change internally without reflecting to your run.
Parameter Studies:
Alternatively if you want this change of the parameter to be applied to multiple runs you could use the advanced built-in approach provided by OMNeT++ which allows you to perform Parameter Studies.
I have explained here how Parameter Studies work: https://stackoverflow.com/a/30572095/4786271 and also here how it can be achieved with constraints etc: https://stackoverflow.com/a/29622426/4786271
If none of the approaches suggested by me fit your case, answers to this question altogether might solve your problem: How to change configuration of network during simulation in OMNeT++?
EDIT: extending the answer to roughly explain handleParameterChange()
I have not used handleParameterChange() before as well, but from what can I see this function provides a watchdog functionality to the module which utilizes it.
To activate this functionality first the void handleParameterChange(const char *parameterName); has to be re-defined.
In essence what it seems to do is the following:
Assume we have two modules moduleA and moduleB and moduleB has parameter parB. moduleA changes the parB and when that happens, moduleB reacts to this change based on the behaviour defined in:
moduleB::handleParameterChange(parB);
The behaviour could be re-reading the original value for parB from the .ini etc.

Setting input parameter for a method

I have an object called X with a method GET_BANK, like in the picture below:
I want to call the function GET_BANK and I am trying to set the input parameter BLZ with a certain value.
I don't quite understand the data structure that is presented here and how I can access it.
At this point my code looks like this (simple version):
data: testobj type ref to ZCO_BLZSERVICE_PORT_TYPE .
data: input type ZGET_BANK .
input-BLZ = '10070000'.
I think the error that I am getting "The data object "INPUT" does not have a component called "BLZ"." is not relevant as I obviously have no idea on how to set the BLZ parameter.
Edit: Getting to BLZ can be done by chaining multiple parameters / objects:
input-PARAMETERS-BLZ = '10070000'.
As far as I can see, your input data should refer to TYPE ZGET_BANK_TYPE. Try double-clicking the field with that content in the screen you showed to see whether it leads to a structure with a component named BLZ.