Does using a string literal like #"key" in setObject(id):forKey(id) only work because the compiler optimizes all instances of the string literal to point to the same object? Or does retrieving an object with objectForKey(id) actually compare the string value of the key?
What if the NSDictionary was created by an external function like JSON parsing? Now when I access the objects using string literals for keys, it would be the first time the compiler sees the key strings and it would not be the same object used by the JSON parser when it created the dictionary.
Should I use valueForKey(NSString *) instead when accessing values from an externally created dictionary?
NSDictionary is a hash table, which means that at first some function is calculated over the key to find the index of value in some array (called hash code, it is a quick operation).
Then, since some keys can produce the same hash value, all keys for this hash code are compared to the one we are searching for.
Related
The available documentation for cordova plugins in iOS is pretty poor, and assumes knowledge of Objective C (which I have never learned). It also seems to skip over certain things you're likely to need to know, like what a CDVInvokedUrlCommand is, exactly, and what types of values can be extracted from it.
I see from the header file for the type that it contains a method argumentAtIndex:, which I presume from Swift examples that I've seen interacts with the swift subscript operator, as these suggest command.arguments[number] as a means of getting the argument. However, I've seen no examples at any point that retrieve an argument of any type other than strings (which return either String or NSString ... and to be honest, I'm not really sure what the difference between these types is). So as I understand it, if I get string values, I can extract them like this:
#objc(myStringAction:)
func myStringAction (command: CDVInvokedUrlCommand) {
let firstString = command.arguments[0] as String;
let secondString = command.arguments[1] as String;
...
}
So, assuming I'm implementing another action myComplexAction which receives: an integer, a floating point number, an array of integers, and an object containing string values. How can I extract these into appropriate variables, and what are the resulting types?
After some research, a little bit of learning to read Objective C, and a whole load of digging in the badly-documented Cordova iOS platform library source code, it turns out that the arguments array in the CDVInvokedUrlCommand class is simply a standard array that is initialized from a JSON string using the standard platform NSJSONSerialization service. Therefore, you can assume that the array contains entries of one of the following types:
NSString, NSNumber, or NSNull for standard basic types.
Note that NSNumber is used to encode boolean values as well as numeric ones
NSArray with the same kind of entry types for any arrays
NSDictionary with NSString keys and the same kind of entry types for object values.
Referencing from Swift, the following conversions to standard Swift value types are handled by the runtime:
NSString can be converted to String using as (or implicitly for Swift 2 or earlier)
NSNumber can be converted to an optional of any Swift numeric type using the as? operator (the conversion will fail if the contained number isn't representable in the target type).
NSNull doesn't get converted, but can be tested for using is
NSDictionary is implicitly convertible to [AnyHashable:Any]
NSArray is implicitly converted to [Any].
I have a method that parses a string value and converts it into a selected data type, but I am having difficulty converting strings with nested data structures, eg:
"[1,2,3,{'hello' => 'world'}]"
Currently I convert using the eval method but this causes a massive security issue because the string is actually input by a user.
Is there a different way in which I can parse these types of string? I have tried JSON.parse but it doesn't like the nested hash inside of the array.
I want to create a type provider with a static parameter that is an array. I thought this might work if the array was of another primitive type (int, string etc), but this seems not to work.
As a motivating use-case, this would, for example, allow specifying header names when using a CSV type provider for .csv files without a header row.
Only primitive types can be used as type provider parameters. The current json type provider gets around that by using a comma separated list of parameters as a string.
I'm thinking perhaps an array is the way to go, but I'm not sure how to only allow arrays of integers. Here's what I'm starting with:
def put_params
params.require(:project).permit(technologies: [])[:technologies]
end
I want to be able to accept an arbitrary number of technology IDs securely.
As long as the technologies param is passed as an array, you just need to use
def put_params
params.require(:project).permit(:technologies)
end
The fundamental part, here, is how you pass the parameter. You need to make sure the parameter is passed as Array. You can read more in the official documentation.
The params hash is not limited to one-dimensional keys and values. It can contain arrays and (nested) hashes. To send an array of values, append an empty pair of square brackets "[]" to the key name:
GET /clients?ids[]=1&ids[]=2&ids[]=3
The actual URL in this example will be encoded as "/clients?ids%5b%5d=1&ids%5b%5d=2&ids%5b%5d=3" as "[" and "]" are not allowed in URLs. Most of the time you don't have to worry about this because the browser will take care of it for you, and Rails will decode it back when it receives it, but if you ever find yourself having to send those requests to the server manually you have to keep this in mind.
The value of params[:ids] will now be ["1", "2", "3"]. Note that parameter values are always strings; Rails makes no attempt to guess or cast the type.
I have a hash value and I want to convert it into string formate but I do not know how to do that.
Here is the hash value
7616db6c232292d2e56a2de9da49ea810d5bb80d53c10e7b07d9521dc88b3177
Hashing technique is a one way algorithm. So that is not possible, sorry.
You can't. A hash is a one-way function. Plus, two strings could theoretically generate the same hash.
BUT. If you had a large enough, pre-computed list of as many hashes as you could generate for each unique string, you could potentially convert your hash back into a string. Although it would require thousands of GB in entries and a lot of time to compute each and every hash. So it practically isn't possible.