Core Media code Objective C to Swift translation does not work - swift

I am trying to follow the example of the AAPLTimedAnnotationWriter example on GitHub (https://github.com/robovm/apple-ios-samples/blob/master/AVTimedAnnotationWriterUsingCustomAnnotationMetadataforMovieWritingandPlayback/AVTimedAnnotationWriter/AAPLTimedAnnotationWriter.m) and implement something similar in my Swift 5.7 code (running on macOS).
Specifically, I ran into issues in translating line #208-218 of the example code.
CMFormatDescriptionRef metadataFormatDescription = NULL;
NSArray *specs = #[
#{(__bridge NSString *)kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier : AAPLTimedAnnotationWriterCircleCenterCoordinateIdentifier,
(__bridge NSString *)kCMMetadataFormatDescriptionMetadataSpecificationKey_DataType : (__bridge NSString *)kCMMetadataBaseDataType_PointF32},
#{(__bridge NSString *)kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier : AAPLTimedAnnotationWriterCircleRadiusIdentifier,
(__bridge NSString *)kCMMetadataFormatDescriptionMetadataSpecificationKey_DataType : (__bridge NSString *)kCMMetadataBaseDataType_Float64},
#{(__bridge NSString *)kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier : AAPLTimedAnnotationWriterCommentFieldIdentifier,
(__bridge NSString *)kCMMetadataFormatDescriptionMetadataSpecificationKey_DataType : (__bridge NSString *)kCMMetadataBaseDataType_UTF8}];
OSStatus err = CMMetadataFormatDescriptionCreateWithMetadataSpecifications(kCFAllocatorDefault, kCMMetadataFormatType_Boxed, (__bridge CFArrayRef)specs, &metadataFormatDescription);
My code:
private func createChapterMetadataFormatDescription() -> CMMetadataFormatDescription? {
let extra: NSArray = [
(
kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier: "mdta/com.example.circle.center.coordinate",
kCMMetadataFormatDescriptionMetadataSpecificationKey_DataType: kCMMetadataBaseDataType_PointF32
),
(
kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier: "mdta/com.example.circle.radius",
kCMMetadataFormatDescriptionMetadataSpecificationKey_DataType: kCMMetadataBaseDataType_Float64
),
(
kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier: "mdta/com.example.comment.field",
kCMMetadataFormatDescriptionMetadataSpecificationKey_DataType: kCMMetadataBaseDataType_UTF8
)
]
var formatDescription: CMMetadataFormatDescription? = nil
if kCVReturnSuccess != CMMetadataFormatDescriptionCreateWithMetadataSpecifications(allocator: kCFAllocatorDefault,
metadataType: kCMMetadataFormatType_Boxed,
metadataSpecifications: extra,
formatDescriptionOut: &formatDescription) { return nil }
return formatDescription
}
The problem is, CMMetadataFormatDescriptionCreateWithMetadataSpecifications() call returned kCMFormatDescriptionError_InvalidParameter error.
What did I do wrong?

It turned out that if I change my code to the following, the function would succeed.
let item1: NSDictionary = [
kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier: "mdta/com.example.circle.center.coordinate",
kCMMetadataFormatDescriptionMetadataSpecificationKey_DataType: kCMMetadataBaseDataType_PointF32
]
let item2: NSDictionary = [
kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier: "mdta/com.example.circle.radius",
kCMMetadataFormatDescriptionMetadataSpecificationKey_DataType: kCMMetadataBaseDataType_Float64
]
let item3: NSDictionary = [
kCMMetadataFormatDescriptionMetadataSpecificationKey_Identifier: "mdta/com.example.comment.field",
kCMMetadataFormatDescriptionMetadataSpecificationKey_DataType: kCMMetadataBaseDataType_UTF8
]
let extra: NSArray = [item1, item2, item3]
......
Not sure why, but maybe the dictionary literals were not properly converted to the format that Core Media was expecting.

Related

How to get data from JSON data

I have JSON like this:
[{"ID" : "351", "Name" : "Cam123 ", "camIP" : "xxx.xxx.xxx.xxx",
"Username" : "admin", "Password" : "damin", "isSupportPin" : "1" },
{"ID" : "352", "Name" : "Cam122 ", "camIP" : "xxx.xxx.xxx.xxx",
"Username" : "admin", "Password" : "damin", "isSupportPin" : "0" }
]
I want to get isSupportPin with result: 1 or 0.
if (x == 1)
{
mybutton.enabled = TRUE;
}
else
{
mybutton.enabled = FALSE;
}
How I can do it?
Assuming you have an NSData object with this data in it:
// Your JSON is an array, so I'm assuming you already know
// this and know which element you need. For the purpose
// of this example, we'll assume you want the first element
NSData* jsonData = /* assume this is your data from somewhere */
NSError* error = nil;
NSArray* array = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
if( !array ) {
// there was an error with the structure of the JSON data...
}
if( [array count] > 0 ) {
// we got our data in Foundation classes now...
NSDictionary* elementData = array[0]; // pick the correct element
// Now, extract the 'isSupportPin' attribute
NSNumber* isSupportPin = elementData[#"isSupportPin"];
// Enable the button per this item
[mybutton setEnabled:[isSupportPin boolValue]];
} else {
// Valid JSON data, but no elements... do something useful
}
The above example code snippet assumes you know which element you want to read (I guess these are user lines or something) and that you know what the JSON attribute names are (e.g., if isSupportPin isn't actually defined in the JSON object returned in that array, it will simply return nil, which will always evaluate to NO when you send it -boolValue).
Finally, the above code is written for ARC and requires Xcode 4.5 or Clang 4.1 and a deployment target of iOS 5.0. If you're not using ARC, building with a legacy version of Xcode, or targeting something earlier than 5.0, you'll have to adjust the code.
Here what you have is an NSArray of NSDictionarys. So using SBJSON library you could do as following
SBJsonParser *parser = [SBJsonParser alloc] init];
NSArray *data = [parser objectFromString:youJson];
for (NSDictionary *d in data)
{
NSString *value = [d objectForKey:#"Name"];
}
The library can be found at http://stig.github.com/json-framework/
Follow the below link that my help you.
http://www.xprogress.com/post-44-how-to-parse-json-files-on-iphone-in-objective-c-into-nsarray-and-nsdictionary/
If you want to get data or Dictionary fron JSONData then use bellow code..
NSString *responseString = [[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] autorelease];
NSArray *resultsArray = [responseString JSONValue];
for(NSDictionary *item in resultsArray)
{
NSDictionary *project = [item objectForKey:#"result"];//use your key name insted of result
NSLog(#"%#",project);
}
and also download JSON Library and tutorial from below link...
http://mobileorchard.com/tutorial-json-over-http-on-the-iphone/

iPhone:Issues when formatting json for server request

I need to make the json params like below.
Final output should be,
{"submissionTime":"\/Date(1331549630849)\/",
"statusId":"0",
"answers":[{"answer":"Yes","qid":167},{"answer":"Hello","qid":168}],
"participantId":"16369",
"token":"t_ikHOXVjlcsSb9Tfdn5RaO54JGQobHodUD5881SKevxy63jwLxe8ZPQvXYss4pR"}
I am trying to make this format. I got the time, statusid, participantid and token. Its fine. But, i am facing problem when making "answers" array.
I use the below code for making the answers json format like below.
NSArray *answerkeys = [NSArray arrayWithObjects:#"answer", #"qid",nil];
NSString *qID = [NSString stringWithFormat:#"%d", [questionidArray objectAtIndex:i] ]; // for loop
NSArray *objectkeys = [NSArray arrayWithObjects:value, qID,nil];
NSString *answerjsonRequest = [pSr makeJSONObject:objectkeys :answerkeys];
answerjsonRequest = [(NSString *)answerjsonRequest stringByReplacingOccurrencesOfString:#"\n" withString:#""];
[textvaluesArray addObject:[NSString stringWithFormat:#"%#", answerjsonRequest]];
and the output is like below.
(
"{ \"answer\" : \"Hello\", \"qid\" : \"220421824\"}",
"{ \"answer\" : \"How are you\", \"qid\" : \"115781136\"}"
)
But, when i am adding all in one in the final output like below,
NSString *jsonRequest = [pSr makeJSONObject:[NSArray arrayWithObjects: participantID, (NULL!=textvaluesArray)?textvaluesArray:#"0", [NSString stringWithFormat:#"%d", statusID], subTime, [appDelegate getSessionToken], nil] :[NSArray arrayWithObjects:#"participantId", #"answers", #"statusId", #"submissionTime", #"token", nil] ];
The final json result is this.
{
"submissionTime" : "\/Date(1331566698)\/",
"token" : "t_hvYoxifLQhxEKfyw1CAgVtgOfA3DjeB9jZ3Laitlyk9fFdLNjJ4Cmv6K8s58iN",
"participantId" : "16371",
"answers" : [
"{ \"answer\" : \"Hello\", \"qid\" : \"220421824\"}",
"{ \"answer\" : \"Hello\", \"qid\" : \"115781136\"}"
],
"statusId" : "0"
}
BUT, this is NOT the one what i want. My expected JSON output is top above mentioned. I tried many ways, but couldn't achieve this. Could someone helping me on this to resolve to get the exact JSON output?
Thank you!
I ran into this issue as well, and created a quick category to take care of the problem.
#interface NSString (ReplaceForJSON)
- (NSString*)replaceEscapedQuotes;
#end
#implementation NSString (ReplaceForJSON)
- (NSString*)replaceEscapedQuotes
{
NSString* returnVal = [self stringByReplacingOccurrencesOfString:#"\\\"" withString:#"\""];
returnVal = [returnVal stringByReplacingOccurrencesOfString:#"\"{" withString:#"{"];
returnVal = [returnVal stringByReplacingOccurrencesOfString:#"}\"" withString:#"}"];
return returnVal;
}
#end

jsonkit decoding

hi im using jsonkit to deserialize json kit data. this is the code i use.
NSString * strResult = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
nslog(#"strresult");
NSDictionary *deserializedData = [strResult objectFromJSONString];
nslog(#"result");
o/p:
"data": {
"translations": [
{
"translatedText": "hello"
}
]
}
}
result {
data = {
translations = (
{
translatedText = "\U091c\U093e\U0928\U093e";
}
);
};
}
what is the problem????? thanks in advance
Try to use http://code.google.com/p/json-framework/.
Your code will look like this. And you need to include #import "JSON.h"
NSString * strResult = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"strresult");
NSDictionary *deserializedData = [strResult JSONValue];
I think the problem is from string encoding.

Parse NSURL query property

I have a URL like myApp://action/1?parameter=2&secondparameter=3
With the property query I get following part of my URL
parameter=2&secondparameter=3
Is there any way easy to put this in a NSDictionary or an Array?
Thx a lot
You can use queryItems in URLComponents.
When you get this property’s value, the NSURLComponents class parses the query string and returns an array of NSURLQueryItem objects, each of which represents a single key-value pair, in the order in which they appear in the original query string.
Swift
let url = "http://example.com?param1=value1&param2=param2"
let queryItems = URLComponents(string: url)?.queryItems
let param1 = queryItems?.filter({$0.name == "param1"}).first
print(param1?.value)
Alternatively, you can add an extension on URL to make things easier.
extension URL {
var queryParameters: QueryParameters { return QueryParameters(url: self) }
}
class QueryParameters {
let queryItems: [URLQueryItem]
init(url: URL?) {
queryItems = URLComponents(string: url?.absoluteString ?? "")?.queryItems ?? []
print(queryItems)
}
subscript(name: String) -> String? {
return queryItems.first(where: { $0.name == name })?.value
}
}
You can then access the parameter by its name.
let url = "http://example.com?param1=value1&param2=param2"
print(url.queryParameters["param1"])
I had reason to write some extensions for this behavior that might come in handy. First the header:
#import <Foundation/Foundation.h>
#interface NSString (XQueryComponents)
- (NSString *)stringByDecodingURLFormat;
- (NSString *)stringByEncodingURLFormat;
- (NSMutableDictionary *)dictionaryFromQueryComponents;
#end
#interface NSURL (XQueryComponents)
- (NSMutableDictionary *)queryComponents;
#end
#interface NSDictionary (XQueryComponents)
- (NSString *)stringFromQueryComponents;
#end
These methods extend NSString, NSURL, and NSDictionary, to allow you to convert to and from query components strings and dictionary objects containing the results.
Now the related .m code:
#import "XQueryComponents.h"
#implementation NSString (XQueryComponents)
- (NSString *)stringByDecodingURLFormat
{
NSString *result = [self stringByReplacingOccurrencesOfString:#"+" withString:#" "];
result = [result stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return result;
}
- (NSString *)stringByEncodingURLFormat
{
NSString *result = [self stringByReplacingOccurrencesOfString:#" " withString:#"+"];
result = [result stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
return result;
}
- (NSMutableDictionary *)dictionaryFromQueryComponents
{
NSMutableDictionary *queryComponents = [NSMutableDictionary dictionary];
for(NSString *keyValuePairString in [self componentsSeparatedByString:#"&"])
{
NSArray *keyValuePairArray = [keyValuePairString componentsSeparatedByString:#"="];
if ([keyValuePairArray count] < 2) continue; // Verify that there is at least one key, and at least one value. Ignore extra = signs
NSString *key = [[keyValuePairArray objectAtIndex:0] stringByDecodingURLFormat];
NSString *value = [[keyValuePairArray objectAtIndex:1] stringByDecodingURLFormat];
NSMutableArray *results = [queryComponents objectForKey:key]; // URL spec says that multiple values are allowed per key
if(!results) // First object
{
results = [NSMutableArray arrayWithCapacity:1];
[queryComponents setObject:results forKey:key];
}
[results addObject:value];
}
return queryComponents;
}
#end
#implementation NSURL (XQueryComponents)
- (NSMutableDictionary *)queryComponents
{
return [[self query] dictionaryFromQueryComponents];
}
#end
#implementation NSDictionary (XQueryComponents)
- (NSString *)stringFromQueryComponents
{
NSString *result = nil;
for(__strong NSString *key in [self allKeys])
{
key = [key stringByEncodingURLFormat];
NSArray *allValues = [self objectForKey:key];
if([allValues isKindOfClass:[NSArray class]])
for(__strong NSString *value in allValues)
{
value = [[value description] stringByEncodingURLFormat];
if(!result)
result = [NSString stringWithFormat:#"%#=%#",key,value];
else
result = [result stringByAppendingFormat:#"&%#=%#",key,value];
}
else {
NSString *value = [[allValues description] stringByEncodingURLFormat];
if(!result)
result = [NSString stringWithFormat:#"%#=%#",key,value];
else
result = [result stringByAppendingFormat:#"&%#=%#",key,value];
}
}
return result;
}
#end
Something like that:
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
for (NSString *param in [url componentsSeparatedByString:#"&"]) {
NSArray *elts = [param componentsSeparatedByString:#"="];
if([elts count] < 2) continue;
[params setObject:[elts lastObject] forKey:[elts firstObject]];
}
Note : This is sample code. All error cases are not managed.
Try this ;)!
NSString *query = #"parameter=2&secondparameter=3"; // replace this with [url query];
NSArray *components = [query componentsSeparatedByString:#"&"];
NSMutableDictionary *parameters = [[NSMutableDictionary alloc] init];
for (NSString *component in components) {
NSArray *subcomponents = [component componentsSeparatedByString:#"="];
[parameters setObject:[[subcomponents objectAtIndex:1] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]
forKey:[[subcomponents objectAtIndex:0] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
All previous posts do not do the url encoding properly. I would suggest the following methods:
+(NSString*)concatenateQuery:(NSDictionary*)parameters {
if([parameters count]==0) return nil;
NSMutableString* query = [NSMutableString string];
for(NSString* parameter in [parameters allKeys])
[query appendFormat:#"&%#=%#",[parameter stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet],[[parameters objectForKey:parameter] stringByAddingPercentEncodingWithAllowedCharacters:NSCharacterSet.URLQueryAllowedCharacterSet]];
return [[query substringFromIndex:1] copy];
}
+(NSDictionary*)splitQuery:(NSString*)query {
if([query length]==0) return nil;
NSMutableDictionary* parameters = [NSMutableDictionary dictionary];
for(NSString* parameter in [query componentsSeparatedByString:#"&"]) {
NSRange range = [parameter rangeOfString:#"="];
if(range.location!=NSNotFound)
[parameters setObject:[[parameter substringFromIndex:range.location+range.length] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding] forKey:[[parameter substringToIndex:range.location] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
else [parameters setObject:[[NSString alloc] init] forKey:[parameter stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
}
return [parameters copy];
}
According to the already very clean answer of Onato I wrote an extension for NSURL in Swift where you can get a query param like this:
e.g. the URL contains the pair param=some_value
let queryItem = url.queryItemForKey("param")
let value = queryItem.value // would get String "someValue"
The extension looks like:
extension NSURL {
var allQueryItems: [NSURLQueryItem] {
get {
let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false)!
let allQueryItems = components.queryItems!
return allQueryItems as [NSURLQueryItem]
}
}
func queryItemForKey(key: String) -> NSURLQueryItem? {
let predicate = NSPredicate(format: "name=%#", key)!
return (allQueryItems as NSArray).filteredArrayUsingPredicate(predicate).first as? NSURLQueryItem
}
}
Here is the extension in swift:
extension NSURL{
func queryParams() -> [String:AnyObject] {
var info : [String:AnyObject] = [String:AnyObject]()
if let queryString = self.query{
for parameter in queryString.componentsSeparatedByString("&"){
let parts = parameter.componentsSeparatedByString("=")
if parts.count > 1{
let key = (parts[0] as String).stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
let value = (parts[1] as String).stringByReplacingPercentEscapesUsingEncoding(NSUTF8StringEncoding)
if key != nil && value != nil{
info[key!] = value
}
}
}
}
return info
}
}
The preferred way to deal with URLs is now NSURLComponents. In particular the queryItems property which returns an NSArray of params.
If you want the params in a NSDictionary, here's a method:
+(NSDictionary<NSString *, NSString *>*)queryParamsFromURL:(NSURL*)url
{
NSURLComponents* urlComponents = [NSURLComponents componentsWithURL:url resolvingAgainstBaseURL:NO];
NSMutableDictionary<NSString *, NSString *>* queryParams = [NSMutableDictionary<NSString *, NSString *> new];
for (NSURLQueryItem* queryItem in [urlComponents queryItems])
{
if (queryItem.value == nil)
{
continue;
}
[queryParams setObject:queryItem.value forKey:queryItem.name];
}
return queryParams;
}
Caveat: URLs can have repeated params, but the dictionary will only contain the last value of any duplicated param. If that is undesirable, use the queryItems array directly.
For those using Bolts Framework you can use:
NSDictionary *parameters = [BFURL URLWithURL:yourURL].inputQueryParameters;
Remember to import:
#import <Bolts/BFURL.h>
If you happen to have Facebook SDK in your project, you also have Bolts. Facebook is using this framework as a dependency.
Swift 2.1
Oneliner:
"p1=v1&p2=v2".componentsSeparatedByString("&").map {
$0.componentsSeparatedByString("=")
}.reduce([:]) {
(var dict: [String:String], p) in
dict[p[0]] = p[1]
return dict
}
// ["p1": "v1", "p2": "v2"]
Used as an extension on NSURL:
extension NSURL {
/**
* URL query string as dictionary. Empty dictionary if query string is nil.
*/
public var queryValues : [String:String] {
get {
if let q = self.query {
return q.componentsSeparatedByString("&").map {
$0.componentsSeparatedByString("=")
}.reduce([:]) {
(var dict: [String:String], p) in
dict[p[0]] = p[1]
return dict
}
} else {
return [:]
}
}
}
}
Example:
let url = NSURL(string: "http://example.com?p1=v1&p2=v2")!
let queryDict = url.queryValues
// ["p1": "v1", "p2": "v2"]
Please note, if using OS X 10.10 or iOS 8 (or later), it's probably better to use NSURLComponents and the queryItems property and create the dictionary from the NSURLQueryItems directly.
Here's a NSURLComponents based NSURL extension solution:
extension NSURL {
/// URL query string as a dictionary. Empty dictionary if query string is nil.
public var queryValues : [String:String] {
get {
guard let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false) else {
return [:]
}
guard let queryItems = components.queryItems else {
return [:]
}
var result:[String:String] = [:]
for q in queryItems {
result[q.name] = q.value
}
return result
}
}
}
A footnote to the NSURL extension is that it's actually possible in Swift to give the property the same name as the existing string property—query. I didn't know until I tried it, but the polymorphism in Swift lets you differ only on the return type. So if the extended NSURL property is public var query: [String:String] it works. I didn't use this in the example as I find it a little bit crazy, but it does work ...
I published a simple class doing the job under MIT:
https://github.com/anegmawad/URLQueryToCocoa
With it you can have arrays and objects in the query, which are collected and glued together
For Example
users[0][firstName]=Amin&users[0][lastName]=Negm&name=Devs&users[1][lastName]=Kienle&users[1][firstName]=Christian
will become:
#{
name : #"Devs",
users :
#[
#{
firstName = #"Amin",
lastName = #"Negm"
},
#{
firstName = #"Christian",
lastName = #"Kienle"
}
]
}
You can think of it as a URL query counterpart of NSJSONSerializer.
It looks that you are using it to process incoming data from another iOS application. If so, this is what I use for the same purpose.
Initial call (e.g. in external application):
UIApplication *application = [UIApplication sharedApplication];
NSURL *url = [NSURL URLWithString:#"myApp://action/1?parameter=2&secondparameter=3"];
if ([application canOpenURL:url]) {
[application openURL:url];
NSLog(#"myApp is installed");
} else {
NSLog(#"myApp is not installed");
}
Method to extract QueryString data from NSURL and save as NSDictionary:
-(NSDictionary *) getNSDictionaryFromQueryString:(NSURL *)url {
NSMutableDictionary *result = [[NSMutableDictionary alloc] init];
NSRange needle = [url.absoluteString rangeOfString:#"?" options:NSCaseInsensitiveSearch];
NSString *data = nil;
if(needle.location != NSNotFound) {
NSUInteger start = needle.location + 1;
NSUInteger end = [url.absoluteString length] - start;
data = [url.absoluteString substringWithRange:NSMakeRange(start, end)];
}
for (NSString *param in [data componentsSeparatedByString:#"&"]) {
NSArray *keyvalue = [param componentsSeparatedByString:#"="];
if([keyvalue count] == 2){
[result setObject:[keyvalue objectAtIndex:1] forKey:[keyvalue objectAtIndex:0]];
}
}
return result;
}
Usage:
NSDictionary *result = [self getNSDictionaryFromQueryString:url];
This class is a nice solution for url parsing.
.h file
#interface URLParser : NSObject {
NSArray *variables;
}
#property (nonatomic, retain) NSArray *variables;
- (id)initWithURLString:(NSString *)url;
- (NSString *)valueForVariable:(NSString *)varName;
#end
.m file
#import "URLParser.h"
#implementation URLParser
#synthesize variables;
- (id) initWithURLString:(NSString *)url{
self = [super init];
if (self != nil) {
NSString *string = url;
NSScanner *scanner = [NSScanner scannerWithString:string];
[scanner setCharactersToBeSkipped:[NSCharacterSet characterSetWithCharactersInString:#"&?"]];
NSString *tempString;
NSMutableArray *vars = [NSMutableArray new];
[scanner scanUpToString:#"?" intoString:nil]; //ignore the beginning of the string and skip to the vars
while ([scanner scanUpToString:#"&" intoString:&tempString]) {
[vars addObject:[tempString copy]];
}
self.variables = vars;
}
return self;
}
- (NSString *)valueForVariable:(NSString *)varName {
for (NSString *var in self.variables) {
if ([var length] > [varName length]+1 && [[var substringWithRange:NSMakeRange(0, [varName length]+1)] isEqualToString:[varName stringByAppendingString:#"="]]) {
NSString *varValue = [var substringFromIndex:[varName length]+1];
return varValue;
}
}
return nil;
}
#end
Hendrik wrote a nice example for extension in this question, however I had to re-write it to not use any objective-c library methods. Using NSArray in swift is not the correct approach.
This is the result, all swift and a bit more safe. The usage example will be less lines of code with Swift 1.2.
public extension NSURL {
/*
Set an array with all the query items
*/
var allQueryItems: [NSURLQueryItem] {
get {
let components = NSURLComponents(URL: self, resolvingAgainstBaseURL: false)!
if let allQueryItems = components.queryItems {
return allQueryItems as [NSURLQueryItem]
} else {
return []
}
}
}
/**
Get a query item form the URL query
:param: key The parameter to fetch from the URL query
:returns: `NSURLQueryItem` the query item
*/
public func queryItemForKey(key: String) -> NSURLQueryItem? {
let filteredArray = filter(allQueryItems) { $0.name == key }
if filteredArray.count > 0 {
return filteredArray.first
} else {
return nil
}
}
}
Usage:
let queryItem = url.queryItemForKey("myItem")
Or, more detailed usage:
if let url = NSURL(string: "http://www.domain.com/?myItem=something") {
if let queryItem = url.queryItemForKey("myItem") {
if let value = queryItem.value {
println("The value of 'myItem' is: \(value)")
}
}
}
try this:
-(NSDictionary *)getUrlParameters:(NSString *)url{
NSArray *justParamsArr = [url componentsSeparatedByString:#"?"];
url = [justParamsArr lastObject];
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
for (NSString *param in [url componentsSeparatedByString:#"&"]) {
NSArray *elts = [param componentsSeparatedByString:#"="];
if([elts count] < 2) continue;
[params setObject:[elts lastObject] forKey:[elts firstObject]];
}
return params;
}
Fairly compact approach:
func stringParamsToDict(query: String) -> [String: String] {
let params = query.components(separatedBy: "&").map {
$0.components(separatedBy: "=")
}.reduce(into: [String: String]()) { dict, pair in
if pair.count == 2 {
dict[pair[0]] = pair[1]
}
}
return params
}
Most robust solution if you are using a URL to pass data from the web app to the phone and you want to pass arrays, numbers, strings, ...
JSON encode your object in PHP
header("Location: myAppAction://".urlencode(json_encode($YOUROBJECT)));
And JSON decode the result in iOS
NSData *data = [[[request URL] host] dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *packed = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];

Need help using json-framework on iPhone

So I've got json-framework up and running on my project, but need help figuring out how to use it to parse this json string:
[
{
"id":"0",
"name":"name",
"info":"This is info",
"tags":
[
{
"id":"36",
"tag":"test tag"
},
{
"id":"37",
"tag":" tag 2"
}
],
"other":"nil"
},
{
"id":"1",
"name":"name",
"info":"This is info",
"tags":
[
{
"id":"36",
"tag":"test tag"
},
{
"id":"37",
"tag":" tag 2"
}
],
"other":"nil"
}
]
Any help and maybe sample code on how to go about this specific type of json would be great. Somehow I can't get it into a dictionary I can read out of. Thanks so much.
The reason why you can't get this string into a dictionary is because it isn't a dictionary, it's an array of dictionaries
You can get the values into an Objective-C object by storing it in an NSArray:
NSArray *objects = (NSArray*) [jsonString JSONValue];
Then, you can loop over those objects that are in the array:
for(NSDictionary *dict in objects) {
NSString *id = (NSString *) [dict objectForKey:#"id"];
NSString *name = (NSString *) [dict objectForKey:#"name"];
NSArray *tags = (NSArray *) [dict objectForKey: #"tags"];
//loop over tags here...
for(NSDictionary *tag in tags) {
NSString *tag_id = (NSString *) [tag objectForKey:#"id"];
NSString *tag_name = (NSString *) [tag objectForKey:#"tag"];
}
//...
}