Get position of NSString in string - iOS - ios

I am developing an iOS app and one of the things I need to do it to go over URLs and replace the first protocol section with my own custom protocol.
How can I delete the first few characters of a NSString before the "://"?
So for example I need convert the following:
http://website.com --> cstp://website.com
ftp://website.com --> oftp://website.com
https://website.com --> ctcps://website.com
The main problem I face, is that I can't just delete the first 'x' number of characters from the URL string. I have to detect how many characters there are till the "://" characters are reached.
So how can I count how many characters there are from that start of the string to the "://" characters?
Once I know this, I can then simply do the following to delete the characters:
int counter = ... number of characters ...
NSString *newAddress = [webURL substringFromIndex:counter];
Thanks for your time, Dan.

http://website.com is a URL, and http is the scheme part of the URL. Instead of string manipulation I would recommend to use the
NSURLComponents class which is made exactly for this purpose: inspect, create and modify URLs:
NSString *originalURL = #"http://website.com";
NSURLComponents *urlcomp = [[NSURLComponents alloc] initWithString:originalURL];
if ([urlcomp.scheme isEqualToString:#"http"]) {
urlcomp.scheme = #"cstp";
} else if ([urlcomp.scheme isEqualToString:#"ftp"]) {
urlcomp.scheme = #"otfp";
}
// ... handle remaining cases ...
NSString *modifiedURL = [urlcomp string];
NSLog(#"%#", modifiedURL); // cstp://website.com
If the number of cases grows then a dictionary mapping is easier to
manage:
NSDictionary *schemesMapping = #{
#"http" : #"cstp",
#"ftp" : #"otfp"
#"https" : #"ctcps" };
NSURLComponents *urlcomp = [[NSURLComponents alloc] initWithString:originalURL];
NSString *newScheme = schemesMapping[urlcomp.scheme];
if (newScheme != nil) {
urlcomp.scheme = newScheme;
}
NSString *modifiedURL = [urlcomp string];

You can use:
NSRange range = [urlString rangeOfString:#"://"];
range.location will give you the first index from where the "://" starts and you can use it as:
NSString *newAddress = [urlString substringFromIndex:range.location];
and append your prefix:
NSString *finalAddress = [NSString stringWithFormat:#"%#%#", prefixString, newAddress];

Related

Regex get string from string

I have NSString that contain this string :
c&&(b.signature=Rk(c));return ql(a,b)}
The RK can be any two chars.
I try to get the RK from the string with (RegexKitLit):
NSString *functionCode = [dataStr2 stringByMatching:#".signature=(.*?)\(" capture:1L];
and functionCode is always nil.Any idea what wrong?
Don't bother with regular expressions for this. If the format of the string is always the same then you can simply do:
NSString *dataStr2 = #"c&&(b.signature=Rk(c));return ql(a,b)}";
NSString *functionCode = [dataStr2 substringWithRange:NSMakeRange(16, 2)];
If the string is not quite so fixed then base it on the position of the =.
NSString *dataStr2 = #"c&&(b.signature=Rk(c));return ql(a,b)}";
NSRange equalRange = [dataStr2 rangeOfString:#"="];
NSString *functionCode = [dataStr2 substringWithRange:NSMakeRange(equalRange.location + equalRange.length, 2)];

NSString find and replace html tags attgibutes

I have pretty simple NSString
f.e
<scirpt attribute_1="x" attribute2="x" attribute3="x" ... attributeX="x"/>
I need to find specific parameter, let's say attribute2 and replace it's value,
I know the exact name of parameter f.e attribute2 but I don't know anything about it's value.
I guess it can be easily done by regexp, but I quite newbie on it.
In conclusion: I want to grab
attribute2="xxxx...xxx"
from incoming string
Note: I don't want to use some 3rd party libs to achieve that (it's temporary hack)
Any help is appreciated
I hacked it together with some string operations:
NSDictionary* valuesToReplace = #{#"attribute_1" : #"newValue1"};
NSString* sourceHtml = #"<scirpt attribute_1=\"x\" attribute2=\"x\" attribute3=\"x\" attributeX=\"x\" />";
NSArray* attributes = [sourceHtml componentsSeparatedByString:#" "];
for (NSString* pair in attributes)
{
NSArray* attributeValue = [pair componentsSeparatedByString:#"="];
if([attributeValue count] > 1) //to skip first "script" element
{
NSString* attr = [attributeValue firstObject]; //get attribute name
if([valuesToReplace objectForKey:attr]) //check if should be replaced
{
NSString* newPair = [NSString stringWithFormat:#"%#=\"%#\"", attr, [valuesToReplace objectForKey:attr]]; //create new string for that attribute
sourceHtml = [sourceHtml stringByReplacingOccurrencesOfString:pair withString:newPair]; //replace it in sourceHtml
}
}
}
It's really only when you want to hack it and you know the format :) Shoot a question if you have any.
you can try this.. https://github.com/mwaterfall/MWFeedParser
import "NSString+HTML.h" along with dependencies
And write like this...
simpletxt.text = [YourHTMLString stringByConvertingHTMLToPlainText];

Adding comment to vimeo videos in iOS

In my ios app when i try to add comments to vimeo videos using video.comment.addcomment, if the comment is only one word it is adding properly, but if it is more than one word it is saying an error that invalid signature.The code i used is:
NSString *new = [NSString stringWithString:commentis];
new = [new stringByReplacingOccurrencesOfString:#" " withString:#"+"];
NSString *url12 = #"http://vimeo.com/api/rest/v2?format=json&method=vimeo.videos.comments.addComment&video_id=123456&comment_text=good";
url12 = [url12 stringByReplacingOccurrencesOfString:#"123456" withString:videoplaying];
url12 = [url12 stringByReplacingOccurrencesOfString:#"good" withString:new];
NSURL *urlinfo = [[NSURL alloc] initWithString:url12];
OAMutableURLRequest *request3 = [[OAMutableURLRequest alloc]initWithURL:urlinfo consumer:consumer token:tokenfi realm:nil signatureProvider:nil];
i dint understand the error.the json response i am getting is
{
err = {
code = 401;
expl = "The oauth_signature passed was not valid.";
msg = "Invalid signature";
};
"generated_in" = "0.0124";
stat = fail;
}
but if i give the comment as single word it is working fine.
Maybe it has something to do with the whitespace and the way you are executing your request. Make sure there is no whitespace in the URL you are formatting.
Replace the whitespace with the URL escape code right before you use the string to create a NSURL. Like this:
url12 = [url12 stringByReplacingOccurrencesOfString:#" " withString:#"%20"];

How to make first letter uppercase in a UILabel?

I'm developing an iPhone app. In a label, I want to show an user's first letter of the name uppercase. How do I do that?
If there is only one word String, then use the method
-capitalized
let capitalizedString = myStr.capitalized // capitalizes every word
Otherwise, for multi word strings, you have to extract first character and make only that character upper case.
(2014-07-24: Currently accepted answer is not correct) The question is very specific: Make the first letter uppercase, leave the rest lowercase. Using capitalizedString produces a different result: “Capitalized String” instead of “Capitalized string”. There is another variant depending on the locale, which is capitalizedStringWithLocale, but it's not correct for spanish, right now it's using the same rules as in english, so this is how I'm doing it for spanish:
NSString *abc = #"this is test";
abc = [NSString stringWithFormat:#"%#%#",[[abc substringToIndex:1] uppercaseString],[abc substringFromIndex:1] ];
NSLog(#"abc = %#",abc);
In case someone is still interested in 2016, here is a Swift 3 extension:
extension String {
func capitalizedFirst() -> String {
let first = self[self.startIndex ..< self.index(startIndex, offsetBy: 1)]
let rest = self[self.index(startIndex, offsetBy: 1) ..< self.endIndex]
return first.uppercased() + rest.lowercased()
}
func capitalizedFirst(with: Locale?) -> String {
let first = self[self.startIndex ..< self.index(startIndex, offsetBy: 1)]
let rest = self[self.index(startIndex, offsetBy: 1) ..< self.endIndex]
return first.uppercased(with: with) + rest.lowercased(with: with)
}
}
Then you use it exactly as you would for the usual uppercased() or capitalized():
myString.capitalizedFirst() or myString.capitalizedFirst(with: Locale.current)
Simply
- (NSString *)capitalizeFirstLetterOnlyOfString:(NSString *)string{
NSMutableString *result = [string lowercaseString].mutableCopy;
[result replaceCharactersInRange:NSMakeRange(0, 1) withString:[[result substringToIndex:1] capitalizedString]];
return result;
}
This is for your NSString+Util category...
- (NSString *) capitalizedFirstLetter {
NSString *retVal;
if (self.length < 2) {
retVal = self.capitalizedString;
} else {
retVal = string(#"%#%#",[[self substringToIndex:1] uppercaseString],[self substringFromIndex:1]);
}
return retVal;
}
You can do that with NSString stringWithFormat, of course. I use this weirdness:
#define string(...) \
[NSString stringWithFormat:__VA_ARGS__]
As an extension to the accepted answer
capitalizedString is used for making uppercase letters .
NSString *capitalizedString = [myStr capitalizedString]; // capitalizes every word
But if you have many words in a string and wants to get only first character as upper case use the below solution
NSString *firstCapitalChar = [[string substringToIndex:1] capitalizedString];
NSString *capString = [string stringByReplacingCharactersInRange:NSMakeRange(0,1) withString: capString];
// extract first character and make only that character upper case.
here's a swift extension for it
extension NSString {
func capitalizeFirstLetter() -> NSString {
return self.length > 1 ?
self.substringToIndex(1).capitalizedString + self.substringFromIndex(1) :
self.capitalizedString
}
}
This is how it worked for me:
NSString *serverString = jsonObject[#"info"];
NSMutableString *textToDisplay = [NSMutableString stringWithFormat:#"%#", serverString];
[textToDisplay replaceCharactersInRange:NSMakeRange(0, 1) withString:[textToDisplay substringToIndex:1].capitalizedString];
cell.infoLabel.text = textToDisplay;
Hope it helps.
Swift:
let userName = "hard CODE"
yourLabel.text = userName.localizedUppercaseString
I recommend using this localised version of uppercase, since names are locale sensitive.

What characters are allowed in a iOS file name?

I'm looking for a way to make sure a string can be used as a file name under iOS. I'm currently in the section of the code that deletes incompatible characters. I'm wondering if I'm doing it right.
NSString *filename = #"A file name";
fileName = [fileName stringByTrimmingCharactersInSet: [NSCharacterSet controlCharacterSet]];
fileName = [fileName stringByTrimmingCharactersInSet: [NSCharacterSet newlineCharacterSet]];
I'm also wondering if there's already a method that validates a string as a file name.
Thank you for your advice!
Use RegEx:
NSRegularExpression *regex = [NSRegularExpression regularExpressionWithPattern:#"[^a-zA-Z0-9_]+" options:0 error:nil];
filename = [regex stringByReplacingMatchesInString:filename options:0 range:NSMakeRange(0, filename.length) withTemplate:#"-"];
I find this to be cleaner and probably much more performant. This is based on Angel Naydenov's solution, but first constructing Character set with all invalid characters and then calling components(separatedBy:) just once.
Swift 3 & 4
var invalidCharacters = CharacterSet(charactersIn: ":/")
invalidCharacters.formUnion(.newlines)
invalidCharacters.formUnion(.illegalCharacters)
invalidCharacters.formUnion(.controlCharacters)
let newFilename = originalFilename
.components(separatedBy: invalidCharacters)
.joined(separator: "")
Swift 2
let invalidCharacters = NSMutableCharacterSet(charactersInString: ":/")
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.newlineCharacterSet())
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.illegalCharacterSet())
invalidCharacters.formUnionWithCharacterSet(NSCharacterSet.controlCharacterSet())
let filename = originalFilename
.componentsSeparatedByCharactersInSet(invalidCharacters)
.joinWithSeparator("")
First of all, you're using the wrong method. Trimming the string will only remove characters in the beginning and the end of the string.
What you're looking for is something more like:
fileName = [fileName stringByReplacingOccurrencesOfString:#"/" withString:#"_"];
However, that's a suboptimal solution, since you'll have to do that for every character you want to exclude, so maybe you want to keep looking or write you're own method for manipulating the string.
iOS is UNIX based and as such I suppose it supports almost any characters in filenames. UNIX allows white spaces, <, >, |, \, :, (, ), &, ;, as well as wildcards such as ? and *, to be quoted or escaped using \ symbol. However I wouldn't use any of those characters in my filenames. In fact, I would restrict the characters in my filenames to 'a'-'z', '0'-'9', '_' and '.'.
As I did not see a list with allowed characters in this question but the question wanted a list with such characters I am adding a bit more details on this topic.
First we need to know what is the file system that iOS devices use. Using multiple online sources this seems to be HFSX which is the HFS+ case sensitive version. And including one link here for reference: https://apple.stackexchange.com/questions/83671/what-filesystem-does-ios-use
Now that we know what the file system is we can look for what characters are not allowed. And these seem to be: colon (:) and slash (/). Here is a link for reference: http://www.comentum.com/File-Systems-HFS-FAT-UFS.html
Having this information and what others have written in this thread my personal preference for removing not allowed characters from file names is the following Swift code:
filename = "-".join(filename.componentsSeparatedByCharactersInSet(NSCharacterSet.newlineCharacterSet()))
filename = "-".join(filename.componentsSeparatedByCharactersInSet(NSCharacterSet.illegalCharacterSet()))
filename = "-".join(filename.componentsSeparatedByCharactersInSet(NSCharacterSet.controlCharacterSet()))
filename = "-".join(filename.componentsSeparatedByString(":"))
filename = "-".join(filename.componentsSeparatedByString("/"))
The reason I am not preferring the RegEx approach is that it seems too restrictive to me. I do not want to restrict my users only to Latin characters. They may as well wish to use some Chinese, Cyrillic or whatever else they like.
Happy coding!
I've had to save remote files locally with filenames containing other characters than basic alpha-numeric characters. I use the method below to strip out potential invalid characters, ensuring it's a valid filename for the filesystem when generating a NSURL using URLWithString:
filename = [[filename componentsSeparatedByCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]] componentsJoinedByString:#"" ];
filename = [[filename componentsSeparatedByCharactersInSet:[NSCharacterSet illegalCharacterSet]] componentsJoinedByString:#"" ];
filename = [[filename componentsSeparatedByCharactersInSet:[NSCharacterSet symbolCharacterSet]] componentsJoinedByString:#"" ];
fileURLString = [NSTemporaryDirectory() stringByAppendingPathComponent:filename];
fileURL = [NSURL URLWithString:fileURLString];
You may also want to test for collision errors first using:
[[NSFileManager defaultManager] fileExistsAtPath:[fileURL absoluteString]]
This String extension (Swift 4.2) will help convert an invalid iOS file name to a valid iOS file name.
extension String {
func convertToValidFileName() -> String {
let invalidFileNameCharactersRegex = "[^a-zA-Z0-9_]+"
let fullRange = startIndex..<endIndex
let validName = replacingOccurrences(of: invalidFileNameCharactersRegex,
with: "-",
options: .regularExpression,
range: fullRange)
return validName
}
}
For example
"name.name?/!!23$$#1asd".convertToValudFileName() // "name-name-23-1asd"
"!Hello.312,^%-0//\r\r".convertToValidFileName() // "-Hello-312-0-"
"/foo/bar/pop?soda=yes|please".convertToValidFileName() // "-foo-bar-pop-soda-yes-please"
I'm pretty happy with this solution:
NSString *testString = #"This*is::/legal.😀,?縦書き 123";
NSString *result = [[[testString componentsSeparatedByCharactersInSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]] filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"length > 0"]] componentsJoinedByString:#"-"];
Output:
"This-is-legal-縦書き-123"
What is this sorcery?
Let me break it up into multiple lines so it's clear what's going on:
NSString *testString = #"This*is::/legal.😀,?縦書き 123";
// Get a character set for everything that's NOT alphanumeric.
NSCharacterSet *nonAlphanumericCharacterSet = [[NSCharacterSet alphanumericCharacterSet] invertedSet];
// Split the string on each non-alphanumeric character, thus removing them.
NSArray *cleanedUpComponentsWithBlanks = [testString componentsSeparatedByCharactersInSet:nonAlphanumericCharacterSet];
// Filter out empty strings ("length" is a KVO-compliant property that the predicate can call on each NSString in the array).
NSArray *cleanedUpComponentsWithoutBlanks = [cleanedUpComponentsWithBlanks filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"length > 0"]];
// Put the components back together and join them with a "-".
NSString *result = [cleanedUpComponentsWithoutBlanks componentsJoinedByString:#"-"];
Enjoy!
Swift 4 Version
Added by john-pang on 2021-09-01 with Swift version:
let testString = "This*is::/legal.😀,?縦書き 123"
// Get a character set for everything that's NOT alphanumeric.
let nonAlphanumericCharacterSet = CharacterSet.alphanumerics.inverted
// Split the string on each non-alphanumeric character, thus removing them.
let cleanedUpComponentsWithBlanks = testString.components(separatedBy: nonAlphanumericCharacterSet)
// Filter out empty strings ("length" is a KVO-compliant property that the predicate can call on each NSString in the array).
let cleanedUpComponentsWithoutBlanks = cleanedUpComponentsWithBlanks.filter { $0.length > 0 }
// Put the components back together and join them with a "-".
let result = cleanedUpComponentsWithoutBlanks.joined(separator: "_")
I came up with the following solution. Works nice so far.
import Foundation
extension String {
func removeUnsupportedCharactersForFileName() -> String {
var cleanString = self
["?", "/", "\\", "*"].forEach {
cleanString = cleanString.replacingOccurrences(of: $0, with: "-")
}
return cleanString
}
}
let a = "***???foo.png"
let validString = a.removeUnsupportedCharactersForFileName()
Base on Marian Answers, here is a string extension to remove any unwanted characters.
extension String {
func stripCharacters() -> String {
var invalidCharacters = CharacterSet(charactersIn: ":/")
invalidCharacters.formUnion(.newlines)
invalidCharacters.formUnion(.illegalCharacters)
invalidCharacters.formUnion(.controlCharacters)
let newString = self
.components(separatedBy: invalidCharacters)
.joined(separator: "_")
return newString
}
}
Example:
let fileName = "Man(lop23/45"
let newFileName = fileName.stripCharacters()
print(newFileName)
Swift 5 extension:
I wanted to remove emojis as well and in windows \ is also an invalid character. So I added symbols charset and backslash \ as well.
extension String {
var validFilename: String {
let invalidCharsets = CharacterSet(charactersIn: ":/\\")
.union(.illegalCharacters)
.union(.controlCharacters)
.union(.symbols)
.union(.newlines)
return self.components(separatedBy: invalidCharsets).joined()
}
}

Resources