I'm using MGTwitterEngine. I've found this post where shows a modification to the current version of MGTwitterEngine.
I've applied this modification and when I'm executing the method returns this:
2012-04-10 01:04:17.908 Otsuka On[27519:707] INFO -> retweet response: 07695198-2526-4FF4-BC46-8D39F7719836
But nothing happens in the timeline of the Twitter account.
The method added to TwitterEngine is:
- (NSString *)sendRetweet:(unsigned long)updateID
{
if (updateID == 0){
return nil;
}
NSString *path = [NSString stringWithFormat:#"statuses/retweet/%u.%#", updateID, API_FORMAT];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
[params setObject:[NSString stringWithFormat:#"%u", updateID] forKey:#"id"];
NSString *body = [self _queryStringWithBase:nil parameters:params prefixed:NO];
return [self _sendRequestWithMethod:HTTP_POST_METHOD path:path
queryParameters:params body:body
requestType:MGTwitterUpdateSendRequest
responseType:MGTwitterStatus];
}
Anyone knows what I'm doing wrong?
Thanks.
I use the following method and it works for me:
- (NSString *)sendRetweet:(MGTwitterEngineID)tweetID {
NSString *path = [NSString stringWithFormat:#"statuses/retweet/%llu.%#", tweetID, API_FORMAT];
return [self _sendRequestWithMethod:HTTP_POST_METHOD path:path
queryParameters:nil body:nil
requestType:MGTwitterRetweetSendRequest
responseType:MGTwitterStatus];
}
UPDATE: Yes, try to use this fork: github.com/mattgemmell/MGTwitterEngine
Finally I've solved the problem using NSString parameter as updateID:
- (NSString *)sendRetweet:(NSString *)updateID
{
NSString *path = [NSString stringWithFormat:#"statuses/retweet/%#.%#", updateID, API_FORMAT];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:0];
[params setObject:[NSString stringWithFormat:#"%#", updateID] forKey:#"id"];
NSString *body = [self _queryStringWithBase:nil parameters:params prefixed:NO];
return [self _sendRequestWithMethod:HTTP_POST_METHOD path:path
queryParameters:params body:body
requestType:MGTwitterUpdateSendRequest
responseType:MGTwitterStatus];
}
Related
- (void)readFolder:(NSString *)str :(NSMutableDictionary *)dict {
NSArray *appFolderContents = [[NSArray alloc] init];
appFolderContents = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:str error:nil];
for (NSString *app in appFolderContents) {
if ([app containsString:#".app"])
{
NSString *appName = [[app lastPathComponent] stringByDeletingPathExtension];
NSString *appPath = [NSString stringWithFormat:#"%#/%#", str, app];
NSString *appBundle = [[NSBundle bundleWithPath:appPath] bundleIdentifier];
// NSLog(#"%# -- %#", appPath, appBundle);
NSArray *jumboTron = [NSArray arrayWithObjects:appName, appPath, appBundle, nil];
[dict setObject:jumboTron forKey:appName];
}
}
}
//This searches for apps
- (void)getAPPList {
NSMutableDictionary *myDict = [[NSMutableDictionary alloc] init];
[self readFolder:#"/Applications" :myDict];
[self readFolder:#"/Applications/Utilities" :myDict];
[self readFolder:#"/System/Library/CoreServices" :myDict];
[self readFolder:#"/Volumes/Macintosh HD/Applications" :myDict ];
// Volumes not named 'Macintosh HD' doesn't work, I'm trying to make it work
[self readFolder:#"/Volumes/*/Applications" :myDict ];
//Some apps are stored in the user's Application folder instead of the main one
[self readFolder:[NSString stringWithFormat:#"%#/Applications", NSHomeDirectory()] :myDict];
//Sometimes people keep apps in Downloads
[self readFolder:[NSString stringWithFormat:#"%#/Downloads", NSHomeDirectory()] :myDict];
//Some apps are stored in the user's Library/Application Support sometimes
[self readFolder:[NSString stringWithFormat:#"%#/Library/Application Support", NSHomeDirectory()] :myDict];
I'm trying to make line 26 ([self readFolder:#"/Volumes/*/Applications" :myDict ]) search all volumes, instead of only searching a volume with a matching/specific name. How can I do this?
I'm using Xcode 9.2
something like this should do the trick (untested)
NSArray *keys = [NSArray arrayWithObjects:NSURLVolumeURLKey, NSURLIsVolumeKey, nil];
NSArray *volumeUrls = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:keys options:NSVolumeEnumerationSkipHiddenVolumes];
for (NSURL *volumeUrl in volumeUrls)
{
BOOL mayBeBootVolume = NO;
NSString* pathToVolume = [volumeUrl path];
[self readFolder: [pathToVolume stringByAppendingString: #"/Applications"];
}
If i enumerate an array i get
<myArray: 0x71b26b0>
<myArray: 0x71b2830>
<myArray: 0x71b2900>
I could take it that myData is behind the pointers listed, but if I wanted to explicitly see (log) the contents at each address, how to do that?
I have tried the &myData to no avail
--
for the benefit of uchuugaka:
-(void)loadObservedItems{
NSString *path = [self observationFilePath];
if ([[NSFileManager defaultManager] fileExistsAtPath:path]) {
NSData *data = [[NSData alloc] initWithContentsOfFile:path];
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
myArray = [unarchiver decodeObjectForKey:#"ObserveKey"];
[unarchiver finishDecoding];
} else {
myArray = [[NSMutableArray alloc] initWithCapacity:10];
}
NSLog(#" %#",myArray);
}
Add to MyClass.m:
-(NSString*)description {
NSMutableDictionary* descDict = [NSMutableDictionary dictionary];
[descDict addObject:someField forKey:#"someField"]
[descDict addObject:anotherField forKey:#"anotherField"];
[descDict addObject:yetAnotherField forKey:#"yetAnotherField"];
return [descDict description];
}
Then just use NSLog(#"myObject is %#", myObject);. Just like the big guys.
Slightly more sophisticated is to (within the method) pre-pend your class name and the object address to the result string, but that's usually unnecessary for simple debugging.
But I think you can do that like this:
return [NSString stringWithFormat:#"%# : %#", [super description], [descDict description]];
I'm having an issue properly accessing an NSDictionary built from Flickr data (the flickr.photosets.getPhotos call). Instead of just showing the content of a description tag, it reads the description tag… along with some unnecessary data and quotes.
For example:
NSLog (#"Item description readout: %#", itemDescriptionPre);
yields this response:
Item description readout: {
"_content" = "This is a caption from a photo drawn through Flickr";
}
I've tried to modify the NSString with this
NSString *descripTruncated = [itemDescriptionPre substringFromIndex:17];
But it didn't causes a crash at runtime. It also doesn't address the items at the end of the item. I apologize since NSString modifications seem to be talked about a lot here, but I couldn't find circumstances that mirror mine.
Here is some more context to my code:
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
NSString *jsonString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"Storing incoming data");
NSDictionary *results = [jsonString JSONValue];
NSLog(#"Building NSDictionary.");
NSArray *photos = [[results objectForKey:#"photoset"] objectForKey:#"photo"];
NSLog(#"Building array from dictionary.");
// Loop through each entry in the dictionary...
for (NSDictionary *photo in photos)
{
NSString *title = [photo objectForKey:#"title"];
NSString *description = [photo objectForKey:#"description"];
[photoTitles addObject:title];
[photoDescriptions addObject:description];
}
NSLog(#"Nicer display for results: %# First image title: %# First image description: %#", results, [photoTitles objectAtIndex:0], [photoDescriptions objectAtIndex:0]);
[self updateDisplay];
}
-(void) updateDisplay{
NSString *capTitle = [[photoTitles objectAtIndex:0] uppercaseString];
photoTitleDisplay.text = capTitle;
NSString *itemDescriptionPre = [photoDescriptions objectAtIndex:0];
NSLog (#"Item description readout: %#", itemDescriptionPre);
}
itemDescriptionPre is actually an NSDictionary. This should work:
NSDictionary *itemDescriptionPre = [photoDescriptions objectAtIndex:0];
NSString *itemDescription = [itemDescriptionPre objectForKey:#"_content"];
Let's say I have an NSURL? Whether or not it already has an empty query string, how do I add one or more parameters to the query of the NSURL? I.e., does anyone know of an implementation of this function?
- (NSURL *)URLByAppendingQueryString:(NSString *)queryString
So that it satisfies this NSURL+AdditionsSpec.h file:
#import "NSURL+Additions.h"
#import "Kiwi.h"
SPEC_BEGIN(NSURL_AdditionsSpec)
describe(#"NSURL+Additions", ^{
__block NSURL *aURL;
beforeEach(^{
aURL = [[NSURL alloc] initWithString:#"http://www.example.com"];
aURLWithQuery = [[NSURL alloc] initWithString:#"http://www.example.com?key=value"];
});
afterEach(^{
[aURL release];
[aURLWithQuery release];
});
describe(#"-URLByAppendingQueryString:", ^{
it(#"adds to plain URL", ^{
[[[[aURL URLByAppendingQueryString:#"key=value&key2=value2"] query] should]
equal:#"key=value&key2=value2"];
});
it(#"appends to the existing query sting", ^{
[[[[aURLWithQuery URLByAppendingQueryString:#"key2=value2&key3=value3"] query] should]
equal:#"key=value&key2=value2&key3=value3"];
});
});
});
SPEC_END
Since iOS 7 you can use NSURLComponents that is very simple to use. Take a look on these examples:
Example 1
NSString *urlString = #"https://mail.google.com/mail/u/0/?shva=1#inbox";
NSURLComponents *components = [[NSURLComponents alloc] initWithString:urlString];
NSLog(#"%# - %# - %# - %#", components.scheme, components.host, components.query, components.fragment);
Example 2
NSString *urlString = #"https://mail.google.com/mail/u/0/?shva=1#inbox";
NSURLComponents *components = [[NSURLComponents alloc] initWithString:urlString];
if (components) {
//good URL
} else {
//bad URL
}
Example 3
NSURLComponents *components = [NSURLComponents new];
[components setScheme:#"https"];
[components setHost:#"mail.google.com"];
[components setQuery:#"shva=1"];
[components setFragment:#"inbox"];
[components setPath:#"/mail/u/0/"];
[self.webview loadRequest:[[NSURLRequest alloc] initWithURL:[components URL]]];
But you can do many other things with NSURLComponents take a look on NSURLComponents class reference on Apple documentation or on this link: http://nshipster.com/nsurl/
Here's an implementation that passes your specs:
#implementation NSURL (Additions)
- (NSURL *)URLByAppendingQueryString:(NSString *)queryString {
if (![queryString length]) {
return self;
}
NSString *URLString = [[NSString alloc] initWithFormat:#"%#%#%#", [self absoluteString],
[self query] ? #"&" : #"?", queryString];
NSURL *theURL = [NSURL URLWithString:URLString];
[URLString release];
return theURL;
}
#end
And here is an implementation for NSString:
#implementation NSString (Additions)
- (NSURL *)URLByAppendingQueryString:(NSString *)queryString {
if (![queryString length]) {
return [NSURL URLWithString:self];
}
NSString *URLString = [[NSString alloc] initWithFormat:#"%#%#%#", self,
[self rangeOfString:#"?"].length > 0 ? #"&" : #"?", queryString];
NSURL *theURL = [NSURL URLWithString:URLString];
[URLString release];
return theURL;
}
// Or:
- (NSString *)URLStringByAppendingQueryString:(NSString *)queryString {
if (![queryString length]) {
return self;
}
return [NSString stringWithFormat:#"%#%#%#", self,
[self rangeOfString:#"?"].length > 0 ? #"&" : #"?", queryString];
}
#end
The iOS8+ modern way
adding (or replacing 'ref' value if exists) ref=impm to url which is on min60.com
if ([[url host] hasSuffix:#"min60.com"]) {
NSURLComponents *components = [[NSURLComponents alloc] initWithURL:url resolvingAgainstBaseURL:NO];
NSURLQueryItem * newQueryItem = [[NSURLQueryItem alloc] initWithName:#"ref" value:#"impm"];
NSMutableArray * newQueryItems = [NSMutableArray arrayWithCapacity:[components.queryItems count] + 1];
for (NSURLQueryItem * qi in components.queryItems) {
if (![qi.name isEqual:newQueryItem.name]) {
[newQueryItems addObject:qi];
}
}
[newQueryItems addObject:newQueryItem];
[components setQueryItems:newQueryItems];
url = [components URL];
}
Just a friendly post for those who don't want to write boilerplate code while building NSURL with NSURLComponents.
Since iOS8 we have NSURLQueryItem that helps building URL request freaking fast.
I wrote a little handy category to ease the work, that you can grab here: URLQueryBuilder
Here is example of how easy it is to work with it:
NSString *baseURL = #"https://google.com/search";
NSDictionary *items = #{
#"q" : #"arsenkin.com",
#"hl" : #"en_US",
#"lr" : #"lang_en"
};
NSURL *URL = [NSURL ars_queryWithString:baseURL queryElements:items];
// https://google.com/search?q=arsenkin.com&hl=en_US&lr=lang_en
I have an extension to NSURLComponents that add query item, in swift:
extension NSURLComponents {
func appendQueryItem(name name: String, value: String) {
var queryItems: [NSURLQueryItem] = self.queryItems ?? [NSURLQueryItem]()
queryItems.append(NSURLQueryItem(name: name, value: value))
self.queryItems = queryItems
}
}
To use,
let components = NSURLComponents(string: urlString)!
components.appendQueryItem(name: "key", value: "value")
If you're using RestKit it provides additions to NSString. One of which is:
- (NSString *)stringByAppendingQueryParameters:(NSDictionary *)queryParameters
So you could do:
NSDictionary *shopParams = [NSDictionary dictionaryWithKeysAndObjects:
#"limit",#"20",
#"location",#"latitude,longitude",
nil];
NSString *pathWithQuery = [#"/api/v1/shops.json" stringByAppendingQueryParameters:shopParams]
As others have mentioned, you can use NSURLComponents to construct URLs.
#implementation NSURL (Additions)
- (NSURL *)URLByAppendingQueryParameters:(NSDictionary *)queryParameters
{
NSURLComponents *components = [[NSURLComponents alloc] initWithURL:self resolvingAgainstBaseURL:NO];
NSMutableArray *queryItems = [NSMutableArray array:components.queryItems];
for (NSString *key in [queryParameters allKeys]) {
NSURLQueryItem *queryItem = [[NSURLQueryItem alloc] initWithName:key value:queryParameters[key]];
[queryItems addObject:queryItem];
}
components.queryItems = queryItems;
return [components URL];
}
#end
NSURL is not mutable so you cannot implement this functionality directly based on NSURL. Instead you will have to obtain the string representation of the URL, append your parameters to that and then create a new NSURL.
This does not sound like a good solution. Unless there is a good reason, it is better to work with strings until the last moment and only create an NSURL when you have your fully formed request.
I created a method to build URLs for me.
- (NSString *)urlFor:(NSString *)path arguments:(NSDictionary *)args
{
NSString *format = #"http://api.example.com/%#?version=2.0.1";
NSMutableString *url = [NSMutableString stringWithFormat:format, path];
if ([args isKindOfClass:[NSDictionary class]]) {
for (NSString *key in args) {
[url appendString:[NSString stringWithFormat:#"&%#=%#", key, [args objectForKey:key]]];
}
}
return url;
}
When I try to build something like below, the URLs aren't encoded, of course.
NSDictionary *args = [NSDictionary dictionaryWithObjectsAndKeys:
#"http://other.com", #"url",
#"ABCDEF", #"apiKey", nil];
NSLog(#"%#", [self urlFor:#"articles" arguments:args]);`
The returned value is http://api.example.com/articles?version=2.0.1&url=http://other.com&apiKey=ABCDEF when it should be http://api.example.com/articles?version=2.0.1&url=http%3A%2F%2Fother.com&apiKey=ABCDEF.
I need to encode both key and value. I searched for something and found CFURLCreateStringByAddingPercentEscapes and stringByAddingPercentEscapesUsingEncoding but none of the tests I made worked.
How can I do it?
IIRC, slashes should be interpreted properly when they're in the query part of a URL. Did you test to see if it still works without encoded slashses? Otherwise, do something like:
if ([args isKindOfClass:[NSDictionary class]]) {
for (NSString *key in [args allKeys]) {
NSString *value = [(NSString*)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)[args objectForKey:key], NULL, CFSTR("/?&:=#"), kCFStringEncodingUTF8) autorelease];
[url appendString:[NSString stringWithFormat:#"&%#=%#", key, value]];
[value release];
}
}
return url;
Note the value of the 4th argument to CFURLCreateStringByAddingPercentEscapes.
You should consider using Google Toolbox for Mac's GTMNSString+URLArguments; it's designed for exactly this purpose.
I'd recommend our KSFileUtilities set of classes. Your example would then be:
- (NSString *)urlFor:(NSString *)path arguments:(NSDictionary *)args
{
NSMutableDictionary *parameters = [NSMutableDictionary dictionaryWithDictionary:args];
[parameters setObject:#"2.0.1" forKey:#"version"];
NSURL *result = [NSURL ks_URLWithScheme:#"http"
host:#"api.example.com"
path:path
queryParameters:parameters;
return [result absoluteString];
}