私の会社には、Salesforceと直接インターフェースするiOSアプリがありますが、大きな欠点が1つあります。ユーザーが不正な文字をアップロードしようとすると、アプリがハングしたり、不正な値を返したり、その他の異常な動作が発生したりします。
神秘的なインターウェブ(ありがとう、MailDrop)で、文字列をフィルタリングし、それらの不正な文字をスラッシュでエスケープする、非常に便利なコードを見つけました。次に、値を文字列で返し、アップサーティング/クエリの準備が整います。
しかし、私が本当に問題を抱えているのは、これをアプリケーションで機能させることです。データは辞書に保存され、さまざまな方法(サーバーへのクエリ、または手動入力)で、アプリケーションのライフサイクルのさまざまな時点で書き込まれます。この気の利いた「escapeSosl」を最も効率的な方法で呼び出す方法がよくわかりません。Core Dataに書き込むたびにこれらの文字をエスケープできる方法はありますか?私が最も恐れているのは、アプリを調べてこれを何百回も呼び出すことです。
エスケープ方法は次のとおりです。
- (NSString *)escapeSosl:(NSString *)src {
// from docs, these are all reserved
NSArray *reserved = [NSArray arrayWithObjects:@"\\", @"&", @"|", @"!", @"{", @"}", @"[", @"]", @"^", @"~", @"*:", @":", @"'" ,@"\"", @"+", @"-", nil];
NSMutableString *s = [NSMutableString stringWithString:src];
NSString *r;
NSEnumerator *e = [reserved objectEnumerator];
while (r = [e nextObject])
[s replaceOccurrencesOfString:r withString:[NSString stringWithFormat:@"\\%@", r] options:NSLiteralSearch range:NSMakeRange(0, [s length])];
return s;
}
私が複雑だと思うのは、これらの脱出のタイミングと、それをそれぞれの状況にどのように適用するかです。たとえば、アプリは、手動で入力された場所、または逆ジオコーディングによって検出された場所を使用して、Salesforceにアカウントを照会します。Salesforceサーバーにデータを要求するアプリの例を次に示します。
-(void)checkServerForLeadMatchingAddressOnAccount:(SFAccount *)account {
currentAccount = account;
//Parse the account location data, removing the last word in the `street` object
NSString *street = account.shippingStreetAddress;
NSMutableArray *streetArray = [[street componentsSeparatedByString:@" "] mutableCopy];
[streetArray removeLastObject];
street = [streetArray componentsJoinedByString:@" "];
street = [street stringByAppendingString:@"_%"];
NSString *city = account.shippingCity;
NSString *state = account.shippingState;
NSString *zip = account.shippingZIP;
//Check for a matching lead on the server. User the callback methods to proceed (either create new data on the server or download to the device
NSLog(@"is connected: %i", self.isConnectedToServer);
if (self.isConnectedToServer){
requestCheckForLead = [[SFRestAPI sharedInstance] requestForQuery:[NSString stringWithFormat:@"SELECT ID, Company, Name, Street, City, State, PostalCode, Phone FROM Lead WHERE PostalCode = '%@' AND Street LIKE '%@' AND City = '%@' AND State = '%@'", zip, street, city, state]];
[[SFRestAPI sharedInstance] send:requestCheckForLead delegate:self];
openTasks++;
} else {
NSLog(@"I can't connect");
[self.serverDelegate serverObjectManager:self communicationSuccessful:NO withResponse:@"Could not connect to the server."];
}
文字をエスケープする可能性のあるもう1つの領域は、サーバーへのアップロードを開始する直前です。アップロードされるものには、アカウント、アカウントの連絡先(1:1 rel。)、アカウントのオポチュニティ(1:1 rel。)、オポチュニティの現在のサービスレベル(1:many rel。)などがあります。
アカウントに関連付けられた連絡先の例を次に示します。文字列と辞書参照の両方を使用しますが、lastNameからfirstNameを解析するための追加のロジックがいくつかあります。これらの操作のタイミングを気にする必要がないようにデータをエスケープしたいと思います。
NSMutableDictionary *contactDict = [NSMutableDictionary new];
if (myAccount.contact.email) {
[contactDict setObject:myAccount.contact.email forKey:@"Email"];
} else {
[contactDict setObject:@"" forKey:@"Email"];
}
if (myAccount.contact.name) {
//Split name in two
NSArray *nameArray = [myAccount.contact.name componentsSeparatedByString:@" "];
NSString *firstName = [nameArray objectAtIndex:0];
NSString *lastName = [nameArray lastObject];
[contactDict setObject:firstName forKey:@"firstName"];
[contactDict setObject:lastName forKey:@"lastName"];
} else {
[contactDict setObject:@"" forKey:@"firstName"];
[contactDict setObject:@"" forKey:@"lastName"];
}
if (myAccount.contact.phone){
[contactDict setObject:myAccount.contact.phone forKey:@"Phone"];
} else {
[contactDict setObject:@"" forKey:@"Phone"];
}
updateContactRequest = [[SFRestAPI sharedInstance] requestForUpdateWithObjectType:@"Contact" objectId:myAccount.createdContactID fields:contactDict];
[[SFRestAPI sharedInstance] send:updateContactRequest delegate:self];
したがって、これは少し大きな質問のように思えるかもしれませんが、コアデータに書き込まれるときはいつでも、上記の「escapeSosl」コードに似たものを使用して、これらのさまざまな辞書の文字をエスケープする方法についてのポインタがありますか? ?