Removing text from NSString between "#" and ":" while keeping the text after it - objective-c

So I'm reading the most recent tweet from a twitter bot and assigning it to a string, but sometimes it tweets directly to users. Here's an example of what that might look like.
NSString tweet = #("#user hey heres my message: BLah blah with symbols!");
//part I want to keep is: " BLah blah with symbols!"
//or it could end up being
NSString tweet = #("#otheruser my msg is: Wow heres some more blah: and a second colon");
//part I want to keep is: " Wow heres some more blah: and a second colon"
I want to always remove the first part that talks to the user, while keeping the message on the end. There are too many different messages to use "stringByReplacingOccurrencesOfString"
I don't want to use "exlude-replies" from the twitter API because this bot is very popular and that would require fetching up to 100 since "count" applies before
any idea how I could do this? I think it has something to do with regular expressions, but I haven't ever used them before or been able to get one working how I want. I would really appreciate the help from anyone whos comfortable with regex
edit: also if a regex won't work for this case, id accept an explanation of the limitation preventing that :)

The easiest solution that I can think of is to create an NSMutable array, by using the NSString function componentsSeparatedBy:#":", and simply remove the first element.
NSMutableArray *tweetArray = [[NSMutableArray alloc] initWithArray: [tweet componentsSeparatedByString:#":"]];
[tweetArray removeObjectAtIndex:0];
Your issue with a colon appearing at random afterwards can be fixed by joining the pieces back together again.
tweet = [tweetArray componentsJoinedByString:#":"];
Edit: Fix an error pointed out by user 'maddy'
You'll have to stick this code in an if statement so that it does not execute in tweets that have a colon normally. You can use the fact that it always begins with #user however.
if ([tweet characterAtIndex:0] == '#' && [tweet characterAtIndex:1] != ' '){
NSMutableArray *tweetArray = [[NSMutableArray alloc] initWithArray: [tweet componentsSeparatedByString:#":"]];
[tweetArray removeObjectAtIndex:0];
tweet = [tweetArray componentsJoinedByString:#":"];
}

You can also use this.
NSString *myString = #"#username is me: by using this as sample text";
NSRange range = [myString rangeOfString:#":"];
NSString *newString= [myString substringFromIndex:range.location];
NSLog(#"New String is : %#", newString);

Related

Having trouble taking an index of an array and making it an NSString

I get an array from a JSON and I parse it into an NSMutableArray (this part is correct and working). I now want to take that array and print the first object to a Label. Here is my code:
NSDictionary *title = [[dictionary objectForKey:#"title"] objectAtIndex:2];
arrayLabel = [title objectForKey:#"label"];
NSLog(#"arrayLabel = %#", arrayLabel); // Returns correct
//Here is where I need help
string = [arrayLabel objectAtIndex:1]; //I do not get the first label (App crashes)
NSLog(#"string = %#", string);
other things that I have already tried are as follows:
string = [NSString stringWithFormat:#"%#", [arrayImage objectAtIndex:1]];
and
string = [[NSString alloc] initWithFormat:#"%#", [arrayImage objectAtIndex:1]];
Any help is greatly appriciated!
EDIT: The app does not return a single value and crashes.
Your code doesn't match the structure of your JSON. In your comment on the deleted answer, you said you got an exception when sending objectAtIndex: to an NSString. In your case, arrayLabel isn't an array when you think it is.
If your JSON has an object, your code needs to treat it as an NSDictionary. Likewise for arrays and NSArray and strings and NSString.
In addition to whatever else was going on, you repeatedly refer to "first" but use the index 1. In most C-based programming languages (and others, as well) the convention is that indexes into arrays are 0-based. So, use index 0 to get the first element.

Keychain kSecValueData with weird not-showing characters at last

I've been searching a solution for this problem, but it seems I'm the only one on the Internet who has encountered a problem like this.
I'm using the keychain wrapper class provided by Apple to store the user and password as it should be stored. When I want to get the user value back, is as easy as doing:
NSString *user = [keychain objectForKey:(id)kSecAttrAccount];
Retriveing the password should be as straightforward as the username:
NSString *pass = [keychain objectForKey:(id)kSecValueData];
But after that, trying to print them with an NSLog, nothing is shown on console AFTER the pass. For example:
NSLog(#"user: <%#>, pass: <%#>, something after the pass", user, pass);
The output of this NSLog is:
user: <123456>, pass: <5433
Invoking [pass length] gives me always a number greater than the actual length of the pass (in this example, 10, when I would say its length is actually 4).
I have no idea of what's going on. I made a workaround to patch this problem while I try to find a proper solution (looking every character's integer value and allowing only the ones which are numbers, letters and some symbols).
Thank you in advance!
The problem here is that you are trying to store a CFDataRef object as an NSString object, and then print it is a string using %#. It is a data object, not a string. If you'd like to see it as a string, you must first convert it into a string. Try something like the code below to convert it into a string before you try to log it:
NSData *passData = [keychain objectForKey:(id)kSecValueData];
NSString *pass = [[NSString alloc] initWithBytes:[passData bytes] length:[passData length] encoding:NSUTF8StringEncoding];
kSecValueData is of type: typedef const void * CFTypeRef;
You shouldn't typecast it to a NSString.
Try directly posting it into the NSLog like this.
NSLog(#"user <%#> pass <%#>", [keychain objectForKey:(id)kSecAttrAccount], [keychain objectForKey:(id)kSecValueData]);
Goodluck!

getting NSArray length/count - Objective C

Well I've looked at similar problems over the site but haven't reached a solution thus far so I must be doing something wrong.
Essentially, I am importing a text file, then splitting each line into an element of an array. Since the text file will be updated etc.. I won't every know the exact amount of lines in the file and therefore how many elements in the array. I know in Java you can do .length() etc.. and supposedly in Objective C you can use 'count' but i'm having no luck returning the length of my array... suggestions?
NSString *filePath = [[NSBundle mainBundle] pathForResource:#"allshows"
ofType:#"txt"];
NSString *fileString = [NSString stringWithContentsOfFile:filePath];
NSArray *lines = [fileString componentsSeparatedByString:#"\n"];
NSUInteger *elements = [lines count];
NSLog(#"Number of Shows : ", elements);
and what is being output is NOTHING. as in "Number of Shows : " - blank, like it didn't even count at all.
Thank you for any help!
You're missing the format string placeholder. It should be:
NSLog(#"Number of shows: %lu", elements);
You need to use a format specifier to print an integer (%d):
NSLog(#"Number of Shows : %d", elements);
Looking at your other post, it seems like you are a Java developer. In Java's System.out, you just append the variables. In Objective-C, I suggest you look at "print format specifiers". Objective-C uses the same format.

\n does not skip to next line in NSString

NSMutableString *a = #"Hi";
NSMutableString *b =[a stringByAppendingString:#"\n\n Hi Again"];
The above doesn't give an error but does not put "Hi Again" on the next line. Why?
EDIT2
I realised after posting, that the OP had NSString in the title but put NSMutableString in the code. I have submitted an edit to change the NSMutableString to NSString.
I will leave this as it still maybe helpful.
Well I am surprised that does not give an error, because you are giving a NSMutableString a NSString.
You need to read the Documentation on NSMutableStrings.
to give you an idea
//non mutable strings
NSString *shortGreetingString = #"Hi";
NSString *longGreetingString = #"Hi Again";
/*mutable string - is created and given a character capacity The number of characters indicated by capacity is simply a hint to increase the efficiency of data storage. The value does not limit the length of the string
*/
NSMutableString *mutableString= [NSMutableString stringWithCapacity:15];
/*The mutableString, now uses an appendFormat to construct the string
each %# in the Parameters for the appendFormat is a place holder for values of NSStrings
listed in the order you want after the comma.
Any other charactars will be included in the construction, in this case the new lines.
*/
[mutableString appendFormat:#"%#\n\n%#",shortGreetingString,longGreetingString];
NSLog (#"mutableString = %#" ,mutableString);
[pool drain];
I think this might help you. You'd rather to use '\r' instead of '\n'
I also had a similar problem and found \n works in LLDB but not in GDB
Try using NSString. You could use:
NSString *a = [NSString stringWithFormat:#"%#\n\n%#", #"Hi", #"Hello again"]
If your string is going in a UIView (e.g a UILabel), you also need to set the number of lines to 0
myView.numberOfLines=0;

IPhone Navigation-Based Application Model

I am making a Navigation-Based Application for the IPhone and I start off with a big list of names (about 100) and I was wondering what would be the quickest and most efficient way to alter the content according to what name the user tapped on in the list.
Right now I change the content according to what the title is like this:
NSString *comparisonString = #"Bill Clinton";
NSString *comparisonString2 = #"Bob Dole";
if (self.title == comparisonString) {
NSString *alterString = [NSString stringWithFormat: #"He is a democrat from North Carolina "];
[appDelegate setModelData:alterString];
}
else if (self.title == comparisonString2) {
NSString *alterString = [NSString stringWithFormat: #"He was born into a family in New York City... "];
[appDelegate setModelData:alterString];
}
would this be the best way to do this? Seems like a lot of code would be repeated. I am brand new to Objective-C and developing for the IPhone, any advice will help me. Thank you!
What you've written so far in those two conditions is equivalent to this (with no if statement):
NSString *alterString = [NSString stringWithFormat: #"Content for %#!", self.title];
[appDelegate setModelData:alterString];
Hope that helps.
All you are doing is changing that same part of the string in both the if and else statements (and presumably more else statements later)
EDIT
ok, looking now at the edited question, you basically have a look up table now. So self.title is the key and you want to use that to lookup another string.
One way to do this is to create a plist with a dictionary that maps each name to a string. Then load that plist and look up the name from there. Something like this:
NSDictionary* people = [NSDictionary dictionaryWithContentsOfFile:pathToThePlist];
NSString *content = [people objectForKey:name];
(BTW, right now you are using '==' for string comparison, you want to use -[NSString isEqualToString:] for that in the future.