用于查询字符串的stringWithFormat中的变量参数列表 [英] Variable argument lists in stringWithFormat for query string

查看:98
本文介绍了用于查询字符串的stringWithFormat中的变量参数列表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当参数计数可变时,用 NSString 建立查询的最聪明的方法是什么?

What is the smartest way to build a query with NSString, when the parameter count is variable?

假设我有一个Web服务,该服务返回由参数列表过滤的国家/地区列表。例如:

Let's say I have a web service, which returns a list of countries filtered by a list of parameters. For example:

NSString *continent = @"europe";
NSString *language  = @"german";
NSString *timeZone  = @"UTC+1";
// to be continued

因此,我的查询字符串为:

Thus my query string would be:

[NSString stringWithFormat:@"/getCountries?continent=%@&language=%@&timezone=%@",
    continent, language, timeZone];

我的回复将包含


奥地利,德国和瑞士

Austria, Germany and Switzerland

因为它们都匹配这三个参数。

because they match all three parameters.

现在,我正在寻找最聪明的方法(例如,不是 if s的意大利面条代码)来构建此查询,此时这些参数的0:n可以零。 (例如,当 * timeZone nil 时,URL中不应包含 timezone = nil )结果应为 NSString

Now I'm looking for the smartest way (e.g. not a spaghetti code of ifs) to build this query, when 0:n of these parameters could be nil. (e.g. when *timeZone is nil, the URL should not contain timezone=nil) The result should be a NSString.

推荐答案

我会做一个能够做到这一点并且正确执行的对象。

I would make an object that does this one thing and does it right.

您需要注意的一件事是确保您避开所有名称和正确的价值观。例如,如果您传递的值为 fred& wilma,则该值不应在URL中显示为 members = fred& wilma,而您需要使用&可以被转义(如%26 )。

One key thing you have to look out for is to make sure that you escape all your names and values properly. For example, if you pass in a value of "fred&wilma", that shouldn't appear as "members=fred&wilma" in the URL—you'd need the & to be escaped (as %26).

您可以在装订时简单地将每个字符串转义,但是忘记这样做就太容易了。在代码中重复的任何内容都很容易错过。

You could simply escape each string as you staple it on, but it would be too easy to forget to do that. Anything that is repeated in the code is too easily missed.

这是我为此创建对象的主要原因。该对象不仅可以将字符串装订在一起,而且可以适当地将它们转义。

That's the main reason I'd make an object for this. That object would not only staple strings together, but also escape them appropriately.

我假设您以后不需要查找键的值。您只想构造一个URL。

I'll assume you don't need to look up values for keys later. You just want to construct a URL.

首先,该对象应私下拥有NSMutableString(而不是公共的 @property -私有 @property 或实例变量)。

First, the object should hold an NSMutableString, privately (not a public @property—either a private @property or an instance variable). It should create this in initialization and hold onto it for its entire life.

对象的指定初始值设定项应类似于 initWithResourceURLString:。此方法向字符串发送 mutableCopy 消息,并将结果分配给实例变量或私有属性。 init 应该引发异常(最容易断言 false )。

The object's designated initializer should be something like initWithResourceURLString:. This method sends the string a mutableCopy message and assigns the result to the instance variable or private property. init should throw an exception (most easily by asserting false).

对象还应为单个 unichar 具有实例变量。 initWithResourceURLString:应将其设置为'?'

The object should also have an instance variable for a single unichar. initWithResourceURLString: should set it to '?'.

对象应响应诸如 setQueryParameterWithName:toValue:之类的消息。每个参数应该是一个字符串。如果任一字符串为 nil ,则该方法仅返回。

The object should respond to a message such as setQueryParameterWithName:toValue:. Each argument should be a string. If either string is nil, the method simply returns.

该方法将每个字符串发送 a stringByAddingPercentEscapesUsingEncoding:消息,然后向可变字符串发送 appendFormat:消息,格式如下:

That method sends each string a stringByAddingPercentEscapesUsingEncoding: message, then sends the mutable string an appendFormat: message with the following format:

%C%@=%@

,其参数为 unichar 实例变量中的字符,转义的参数名称和转义的值。然后将字符变量设置为&

with the arguments being the character in the unichar instance variable, the escaped parameter name, and the escaped value. It then sets the character variable to &.

对象应响应诸如 constructedURLString ,返回可变字符串的副本(如果使用MRC,则自动释放)。

The object should respond to a message such as constructedURLString by returning a copy (autoreleased if you're using MRC) of the mutable string.

然后您将使用该对象像这样:

You would then use that object like so:

builder = [[MyURLBuilder alloc] initWithResourceURLString:@"http://example.com/getCountries"]; //Add autorelease under MRC
[builder setQueryParameterName:@"continent" toValue:continent];
[builder setQueryParameterName:@"language" toValue:language];
[builder setQueryParameterName:@"timeZone" toValue:timeZone];
NSURL *finishedURL = [NSURL URLWithString:[builder constructedURLString]];

优点:


  • 您只有一个地方可以确保正确处理转义。所有其他代码都不必担心。

  • 您只有一个地方可以确保处理 nil (忽略) )正确。所有其他代码都不必担心。

  • 订单被保留。字典可能会更改参数的顺序。这无关紧要(服务器无关紧要),但是如果需要,那么您需要一个保留订单的解决方案。

  • 为此对象编写单元测试很容易

  • 如果需要,可以在多个方向上修改此对象。例如,您可以添加对重置构造的查询URL的支持,而无需修改或不必记住基本URL,从而使您可以将该对象重用于多个查询。您还可以添加支持,用空字符串替换 nil 替换任何或仅替换某些参数。您对课程所做的任何更改都将立即提供给您可能具有的其他任何URL构建作业。

  • You have exactly one place in which to make sure escaping is handled correctly. All other code should not need to worry about it.
  • You have exactly one place in which to make sure nil is handled (ignored) correctly. All other code should not need to worry about it.
  • Order is preserved. A dictionary may change the order of the arguments. This shouldn't matter (the server shouldn't care), but if it does, then you need an order-preserving solution.
  • It would be easy to write unit tests for this object.
  • If you want, you can modify this object in a number of directions. You could, for example, add support for resetting the constructed query URL without modifying or having to separately remember the base URL, enabling you to reuse this object for multiple queries. You could also add support for substituting the empty string for nil for any or for only some parameters. Any changes you make to the class would immediately be available to any other URL-building jobs you may have.

这篇关于用于查询字符串的stringWithFormat中的变量参数列表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆