IOS рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдореЗрдВ Vkontakte.ru рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░реЗрдВ

рдЗрд╕ рдЫреЛрдЯреЗ рд▓реЗрдЦ рдореЗрдВ, рдореИрдВ Vkontakte API рдХреЛ iOS рдкреНрд░реЛрдЬреЗрдХреНрдЯ рдореЗрдВ рдПрдХреАрдХреГрдд рдХрд░рдиреЗ рдХреЗ рддрд░реАрдХреЗ рд╕рд╛рдЭрд╛ рдХрд░рдирд╛ рдЪрд╛рд╣реВрдВрдЧрд╛ред
рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рдЕрднреА рдЗрдВрдЯрд░рдиреЗрдЯ рдкрд░ рдмрд╣реБрдд рдХрдо рдЬрд╛рдирдХрд╛рд░реА рд╣реИ рдФрд░ рд╢рд╛рдпрдж рдореЗрд░реА рд╕рд▓рд╛рд╣ рдХрд┐рд╕реА рдХреА рдорджрдж рдХрд░реЗрдЧреАред рдореИрдВ рджрд┐рдЦрд╛рдКрдВрдЧрд╛ рдХрд┐ рдЖрдк рди рдХреЗрд╡рд▓ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдбреЗрдЯрд╛ рдХреИрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдмрд▓реНрдХрд┐ рджреАрд╡рд╛рд░ рдкрд░ рдПрдХ рдлреЛрдЯреЛ, рдкрд╛рда рдФрд░ рд▓рд┐рдВрдХ рднреА рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВ, рд╕рд╛рде рд╣реА рдХреИрдкреНрдЪрд╛ рдЗрдирдкреБрдЯ рдХреЗ рд╕рд╛рде рдПрдХ рдорд╛рдорд▓рд╛ рднреА рдбрд╛рд▓ рд╕рдХрддреЗ рд╣реИрдВред

рдЙрджрд╛рд╣рд░рдг рдХреЗ рд╕рд╛рде рдПрдХ рдкрд░рд┐рдпреЛрдЬрдирд╛ github.com рдкрд░ рд╣реИ - https://github.com/maiorov/VKAPI

рд╡реАрдХреЗ рдПрдкреАрдЖрдИ рд╡рд┐рдзрд┐рдпреЛрдВ рдкрд░ рдкреНрд░рд▓реЗрдЦрди рдпрд╣рд╛рдВ рдкрд╛рдпрд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред

рдЗрд╕ рд╡рд┐рд╖рдп рдкрд░ рдЕрдиреНрдп рд╕реНрд░реЛрддреЛрдВ рд╕реЗ рд▓реЗрдЦ:
1. appleinsider.ru
2. imaladec.net

рддреЛ, рд╡реАрдХреЗ рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдХрд╛рдо рдХрд░рдиреЗ рдореЗрдВ рдХреБрдЫ рдХрджрдо:
1. UIWebView рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдФрд░ accessToken'a рдФрд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЖрдИрдбреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛ред
2. рд╡реАрдХреЗ рдПрдкреАрдЖрдИ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛, рдбреЗрдЯрд╛ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рдирд╛ рдФрд░ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛:
2.1 рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рджреАрд╡рд╛рд░ рдкрд░ рдкрд╛рда рднреЗрдЬрдирд╛
реи.рез.рез рдХреИрдкреНрдЪрд╛
реи.реи рдПрдХ рджреАрд╡рд╛рд░ рдкрд░ рдПрдХ рдЫрд╡рд┐ рдкреЛрд╕реНрдЯ рдХрд░рдирд╛
2.2.1 рдЫрд╡рд┐ рдЕрдкрд▓реЛрдб рдХреЗ рд▓рд┐рдП рд╡реАрдХреЗ рд╕рд░реНрд╡рд░ рдпреВрдЖрд░рдПрд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛
реи.реи.реи рдПрдХ POST рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░реЗрдВ
2.2.3 VKontakte рд╕рд░реНрд╡рд░ рдкрд░ рдлрд╝реЛрдЯреЛ рд╕рд╣реЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрд░реЛрдз рдмрдирд╛рдПрдБ
реи.реи.рек рджреАрд╡рд╛рд░ рдкрд░ рдлреЛрдЯреЛ рд▓рдЧрд╛рдПрдВ
3. рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд▓реЙрдЧрдЖрдЙрдЯ

рднрд╛рдЧ 0. рдЖрд╡реЗрджрди рдкрдВрдЬреАрдХрд░рдг
рдЬреИрд╕рд╛ рдХрд┐ рдпрд╣ рдирд┐рдХрд▓рд╛, рдСрдкрд░реЗрд╢рди рдХрд╛ рд╕рдмрд╕реЗ рддреБрдЪреНрдЫ рд╣рд┐рд╕реНрд╕рд╛ рдирд╣реАрдВ, рдЗрд╕ рддрдереНрдп рдХреЗ рдХрд╛рд░рдг рдХрд┐ рд╡реАрдХреЗрдУрдиреНрдХрдЯреЗ рдХреЗ рдкрд╛рд╕ рдХреЙрд▓рд┐рдВрдЧ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рд▓рд┐рдП рдХрдИ рд░реВрдк рд╣реИрдВ! рдЙрдЪрд┐рдд рдкрдВрдЬреАрдХрд░рдг рдХреЗ рд▓рд┐рдП, рдЖрдкрдХреЛ http://vkontakte.ru/editapp?act=create&site=1 рд▓рд┐рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдирд╛ рд╣реЛрдЧрд╛, рдЖрд╡реЗрджрди рд╕реНрдЯреИрдВрдбрдЕрд▓реЛрди-рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдХреЗ рдкреНрд░рдХрд╛рд░ рдХрд╛ рдЪрдпрди рдХрд░реЗрдВред рд╕реЗрдЯрд┐рдВрдЧреНрд╕ рдореЗрдВ рдкреИрд░рд╛рдореАрдЯрд░ рдЫреЛрдбрд╝рд╛ рдЬрд╛ рд╕рдХрддрд╛ рд╣реИред рдЖрдкрдХреЛ рдмрд╕ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЖрдИрдбреА рдХреА рдкреНрд░рддрд┐рд▓рд┐рдкрд┐ рдмрдирд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдореЗрд░реЗ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдЗрд╕ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП appID рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИред

рднрд╛рдЧ 1. рдкреНрд░рд╛рдзрд┐рдХрд░рдг
рд╡реАрдХреЗ рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде Oauth 2.0 рдкреНрд░реЛрдЯреЛрдХреЙрд▓ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рд╣рдореЗрдВ accessToken рдФрд░ user_id рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рд╣рдо UIKebView рд╡реЗрдм рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ VK рд╕рд░реНрд╡рд░ рдХреЛ рдПрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬрдХрд░ рдЗрд╕реЗ рдкреНрд░рд╛рдкреНрдд рдХрд░ рд╕рдХрддреЗ рд╣реИрдВ, рдЕрдиреБрд░реЛрдз рдХреЗ рдЬрд╡рд╛рдм рдореЗрдВ, VKontakte рд╕рд░реНрд╡рд░ рдПрдХ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдлреЙрд░реНрдо рдЬрд╛рд░реА рдХрд░реЗрдЧрд╛, рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдкрд╛рд░рд┐рдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж рд╣рдореЗрдВ рдПрдХреНрд╕реЗрд╕рдЯреЛрдХрди рдорд┐рд▓реЗрдЧрд╛, user_id (рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХрд╛ рдЖрдИрдбреА рдЬрд┐рд╕рдиреЗ рдЕрдкрдирд╛ рдбреЗрдЯрд╛ рджрд░реНрдЬ рдХрд┐рдпрд╛ рд╣реИ), expires_in (рдЯреЛрдХрди рд╡реИрдзрддрд╛ рд╕рдордп) ред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдПрдХ рдирдИ рдкрд░рд┐рдпреЛрдЬрдирд╛ рдореЗрдВ рдПрдХ рджреГрд╢реНрдп-рдирд┐рдпрдВрддреНрд░рдХ рдмрдирд╛рдПрдВ, рдЖрдЗрдП рдЗрд╕реЗ рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП рдирд╛рдо рджреЗрдВ vkLoginViewControllerред рдпрд╣ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдЕрдзрд┐рдХреГрдд рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЬрд┐рдореНрдореЗрджрд╛рд░ рдирд┐рдпрдВрддреНрд░рдХ рд╣реЛрдЧрд╛, рд╕рдлрд▓ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╣реЛрдиреЗ рдкрд░, рдпрд╣ NSUserDefaults рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рдорд╛рдкрджрдВрдбреЛрдВ рдХреЛ рдмрдЪрд╛рдПрдЧрд╛ рдФрд░ рдкреНрд░рддрд┐рдирд┐рдзрд┐ рд╡рд┐рдзрд┐ рдХреЛ рдкреВрд░реНрдг рдХрд░реЗрдЧрд╛ред

рдЖрдк рдЙрджрд╛рд╣рд░рдг рдореЗрдВ рд╡рд┐рд╕реНрддреГрдд рдХреЛрдб рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред рдпрд╣рд╛рдВ рдореИрдВ рдХреЗрд╡рд▓ рдореБрдЦреНрдп рдмрд┐рдВрджреБрдУрдВ рдХрд╛ рд╡рд┐рд╢реНрд▓реЗрд╖рдг рдХрд░реВрдВрдЧрд╛ред

рдирд┐рдпрдВрддреНрд░рдХ UIWebView * vkWebView рдореЗрдВ рдЬреЛрдбрд╝рдХрд░, рд╣рдо рдПрдХ рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╣реИрдВ:
NSString *authLink = [NSString stringWithFormat:@"http://api.vk.com/oauth/authorize?client_id=%@&scope=wall,photos&redirect_uri=http://api.vk.com/blank.html&display=touch&response_type=token", appID]; NSURL *url = [NSURL URLWithString:authLink]; [vkWebView loadRequest:[NSURLRequest requestWithURL:url]]; 

рдпрд╣рд╛рдВ client_id рдЖрдкрдХреЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди, рд╕реНрдХреЛрдк = рджреАрд╡рд╛рд░ рдХреА рдЖрдИрдбреА рд╣реИ, рдлреЛрдЯреЛ рдПрдХреНрд╕реЗрд╕ рдЕрдзрд┐рдХрд╛рд░ рд╣реИрдВ рдЬреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд╕реЗ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рдЕрдиреБрд░реЛрдз (рджреАрд╡рд╛рд░ рдкрд░ рджреАрд╡рд╛рд░ рдкреНрд▓реЗрд╕рдореЗрдВрдЯ, рдлреЛрдЯреЛ рджреАрд╡рд╛рд░ рдкрд░ рдЪрд┐рддреНрд░ рд▓рдЧрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ)

WebViewDidFinishLoad рдлрд╝рдВрдХреНрд╢рди рдореЗрдВ, рд╣рдореЗрдВ VK рд╕рд░реНрд╡рд░ рд╕реЗ рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдорд┐рд▓рддреА рд╣реИ:
 -(void)webViewDidFinishLoad:(UIWebView *)webView { //      if ([vkWebView.request.URL.absoluteString rangeOfString:@"access_token"].location != NSNotFound) { NSString *accessToken = [self stringBetweenString:@"access_token=" andString:@"&" innerString:[[[webView request] URL] absoluteString]]; //  id ,    NSArray *userAr = [[[[webView request] URL] absoluteString] componentsSeparatedByString:@"&user_id="]; NSString *user_id = [userAr lastObject]; NSLog(@"User id: %@", user_id); if(user_id){ [[NSUserDefaults standardUserDefaults] setObject:user_id forKey:@"VKAccessUserId"]; } if(accessToken){ [[NSUserDefaults standardUserDefaults] setObject:accessToken forKey:@"VKAccessToken"]; //    .  expires_in=86400   ,     . //   ,   ,          [[NSUserDefaults standardUserDefaults] setObject:[NSDate date] forKey:@"VKAccessTokenDate"]; [[NSUserDefaults standardUserDefaults] synchronize]; } NSLog(@"vkWebView response: %@",[[[webView request] URL] absoluteString]); [(ViewController *)delegate authComplete]; [self dismissModalViewControllerAnimated:YES]; } else if ([vkWebView.request.URL.absoluteString rangeOfString:@"error"].location != NSNotFound) { NSLog(@"Error: %@", vkWebView.request.URL.absoluteString); [self dismissModalViewControllerAnimated:YES]; } } 


рдЙрд╕рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рд╡рд╣ рд╕рдм рдХреБрдЫ рдорд┐рд▓рд╛ рдЬрд┐рд╕рдХреА рд╣рдореЗрдВ рдЬрд╝рд░реВрд░рдд рдереА: accessToken, user_idред рдФрд░ рд╣рдо рдкреНрд░рддрд┐рдирд┐рдзрд┐ рдХреЛ рд╕рдВрджреЗрд╢ рджреЗрддреЗ рд╣реИрдВ рдХрд┐ рдкреНрд░рд╛рдзрд┐рдХрд░рдг рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкреВрд░рд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИ, рд╣рдореЗрдВ рдЕрдм рдЗрд╕ рдирд┐рдпрдВрддреНрд░рдХ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ рдФрд░ рд╣рдо рдЗрд╕реЗ рд╣рдЯрд╛ рджреЗрддреЗ рд╣реИрдВ:
 [(ViewController *)delegate authComplete]; [self dismissModalViewControllerAnimated:YES]; 


рднрд╛рдЧ 2. рдПрдкреАрдЖрдИ рдЕрдиреБрд░реЛрдз
рдЕрдм рд╢реБрд░реВ рд╣реЛрддреА рд╣реИ рдорд╕реНрддреА! ViewController рдореЗрдВ рдЙрджрд╛рд╣рд░рдг рдореЗрдВ, рдореИрдВрдиреЗ рдХрдИ рдлрд╝рдВрдХреНрд╢рди рддреИрдпрд╛рд░ рдХрд┐рдП рд╣реИрдВ рдЬрд┐рдирдХреЗ рджреНрд╡рд╛рд░рд╛ рдЖрдк рд╕рдордЭ рд╕рдХрддреЗ рд╣реИрдВ рдХрд┐ рдПрдкреАрдЖрдИ рдХреЗ рд╕рд╛рде рдХреИрд╕реЗ рдХрд╛рдо рдХрд┐рдпрд╛ рдЬрд╛рдПред

2.1 рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рджреАрд╡рд╛рд░ рдкрд░ рдкрд╛рда рднреЗрдЬрдирд╛
рдЙрджрд╛рд╣рд░рдг рдХреЗ рд▓рд┐рдП, рджреАрд╡рд╛рд░ рдкрд░ рдкрд╛рда рднреЗрдЬрдиреЗ рдХрд╛ рдХрд╛рд░реНрдп:
 - (void) sendText { NSString *user_id = [[NSUserDefaults standardUserDefaults] objectForKey:@"VKAccessUserId"]; NSString *accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"VKAccessToken"]; NSString *text = @"   API !"; //        NSString *sendTextMessage = [NSString stringWithFormat:@"https://api.vk.com/method/wall.post?owner_id=%@&access_token=%@&message=%@", user_id, accessToken, [self URLEncodedString:text]]; NSLog(@"sendTextMessage: %@", sendTextMessage); //            NSDictionary *result = [self sendRequest:sendTextMessage withCaptcha:NO]; //       NSString *errorMsg = [[result objectForKey:@"error"] objectForKey:@"error_msg"]; if(errorMsg) { [self sendFailedWithError:errorMsg]; } else { [self sendSuccessWithMessage:@"   !"]; } } 

рд╕рд╛рджрдЧреА рдХреЗ рд▓рд┐рдП, рдореИрдВ NSUserDefaults рдореЗрдВ рдбреЗрдЯрд╛ рд╕рдВрдЧреНрд░рд╣реАрдд рдХрд░рддрд╛ рд╣реВрдВред рдкреНрд░рд╛рдзрд┐рдХрд░рдг рдкреВрд░рд╛ рд╣реЛ рдЧрдпрд╛ рд╣реИ, рдЬрд┐рд╕рдХрд╛ рдЕрд░реНрде рд╣реИ рдХрд┐ рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд╣рдорд╛рд░реЗ рдкрд╛рд╕ рд╕рдм рдХреБрдЫ рд╣реИред Wall.post рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП , рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЖрдИрдбреА (рдорд╛рд▓рд┐рдХ_ рдЖрдИрдбреА) рдФрд░ рдЯреЛрдХрди (рдПрдХреНрд╕реЗрд╕_рдЯреЛрдХрди) рдкрд╛рд╕ рдХрд░рддреЗ рд╣реИрдВ, рд╣рдо рдкрд╣рд▓реЗ URLEncodedString рдлрд╝рдВрдХреНрд╢рди рдХреЗ рдорд╛рдзреНрдпрдо рд╕реЗ рд╕рдВрджреЗрд╢ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд▓рд┐рдП рдкрд╛рда рд╕рдВрджреЗрд╢ рдЪрд▓рд╛рддреЗ рд╣реИрдВ:
 //         - (NSString *)URLEncodedString:(NSString *)str { NSString *result = (NSString *)CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault, (CFStringRef)str, NULL, CFSTR("!*'();:@&=+$,/?%#[]"), kCFStringEncodingUTF8); [result autorelease]; return result; } 


рдЕрдиреБрд░реЛрдз рддреИрдпрд╛рд░ рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЗрд╕реЗ рд╕рд░реНрд╡рд░ рдкрд░ рднреЗрдЬрдирд╛ рд╣реЛрдЧрд╛:
 [self sendRequest:sendTextAndLinkMessage withCaptcha:NO]; 
рдЬреИрд╕рд╛ рдХрд┐ рдЖрдк рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВ, рдлрд╝рдВрдХреНрд╢рди withCaptcha рдкреИрд░рд╛рдореАрдЯрд░ рдХреЛ рд╕реНрд╡реАрдХрд╛рд░ рдХрд░рддрд╛ рд╣реИ: (BOOL) рд╣рдореЗрдВ рдЗрд╕рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрдЧреА рдпрджрд┐ рд╕рд░реНрд╡рд░ рдХреЛ рдХрд╛рд░реНрд░рд╡рд╛рдИ рдХреА рдкреБрд╖реНрдЯрд┐ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХреИрдкреНрдЪрд╛ рджрд░реНрдЬ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЪреВрдВрдХрд┐ рдЕрднреА рддрдХ рдХрд┐рд╕реА рдХреИрдкреНрдЪрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдирд╣реАрдВ рд╣реИ, рдЗрд╕рд▓рд┐рдП рд╣рдо NO рдХреЛ рд╕реНрдерд╛рдирд╛рдВрддрд░рд┐рдд рдХрд░рддреЗ рд╣реИрдВред

рджрд░рдЕрд╕рд▓, рдлрдВрдХреНрд╢рди рднреЗрдЬрдиреЗ рдХрд╛ рдЕрдиреБрд░реЛрдз рд╕реНрд╡рдпрдВ:
 - (NSDictionary *) sendRequest:(NSString *)reqURl withCaptcha:(BOOL)captcha { //      ,      captcha_sid  captcha_key if(captcha == YES){ NSString *captcha_sid = [[NSUserDefaults standardUserDefaults] objectForKey:@"captcha_sid"]; NSString *captcha_user = [[NSUserDefaults standardUserDefaults] objectForKey:@"captcha_user"]; //      .  ,      . reqURl = [reqURl stringByAppendingFormat:@"&captcha_sid=%@&captcha_key=%@", captcha_sid, [self URLEncodedString: captcha_user]]; } NSLog(@"Sending request: %@", reqURl); NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:reqURl] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0]; //      NSURLConnection,     NSData NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; //    ,        JSONKit  NSDictionary if(responseData){ NSDictionary *dict = [[JSONDecoder decoder] parseJSONData:responseData]; //       NSString *errorMsg = [[dict objectForKey:@"error"] objectForKey:@"error_msg"]; NSLog(@"Server response: %@ \nError: %@", dict, errorMsg); //    .      Captcha needed,     . if([errorMsg isEqualToString:@"Captcha needed"]){ isCaptcha = YES; //     NSString *captcha_sid = [[dict objectForKey:@"error"] objectForKey:@"captcha_sid"]; NSString *captcha_img = [[dict objectForKey:@"error"] objectForKey:@"captcha_img"]; [[NSUserDefaults standardUserDefaults] setObject:captcha_img forKey:@"captcha_img"]; [[NSUserDefaults standardUserDefaults] setObject:captcha_sid forKey:@"captcha_sid"]; //  url         [[NSUserDefaults standardUserDefaults] setObject:reqURl forKey:@"request"]; [[NSUserDefaults standardUserDefaults] synchronize]; [self getCaptcha]; } return dict; } return nil; } 

рдлрд╝рдВрдХреНрд╢рди рд╕рд░реНрд╡рд░ рд╕реЗ NS Shadow рдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рджреЗрддрд╛ рд╣реИ; JSONKit рдХрд╛ рдЙрдкрдпреЛрдЧ рдЗрд╕реЗ рдЬреЗрдирд░реЗрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдХрд┐рдпрд╛ рдЬрд╛рддрд╛ рд╣реИ, рдХреНрдпреЛрдВрдХрд┐ рдбрд┐рдлрд╝реЙрд▓реНрдЯ рд░реВрдк рд╕реЗ JSON рдкреНрд░рд╛рд░реВрдк рдореЗрдВ VKontakte рдкреНрд░рддрд┐рд╕рд╛рдж рджреЗрддрд╛ рд╣реИред

рдХреИрдкреНрдЪрд╛
рдпрджрд┐ рдЕрдЪрд╛рдирдХ рд╕рд░реНрд╡рд░ рдиреЗ рдлреИрд╕рд▓рд╛ рдХрд┐рдпрд╛ рдХрд┐ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдХреИрдкреНрдЪрд╛ рджрд░реНрдЬ рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рд╡рд╣ рдЕрдиреБрд░реЛрдз рдХреЗ рдЬрд╡рд╛рдм рдореЗрдВ, рдкрд╛рда рдХреЗ рд╕рд╛рде рдПрдХ рддреНрд░реБрдЯрд┐ рд▓реМрдЯрд╛рдПрдЧрд╛: рдХреИрдкреНрдЪрд╛ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рдФрд░ рдкреИрд░рд╛рдореАрдЯрд░ - рдХреИрдкреНрдЪрд╛_рдПрд╕рдЖрдИрдбреА (рдпрд╣ рдХреИрдкреНрдЪрд╛ рдЖрдИрдбреА рд╣реИ), рдХреИрдкреНрдЪрд╛_рдордЧ (рдХреИрдкреНрдЪрд╛ рдЫрд╡рд┐ рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдХ)ред рдЗрди рдорд╛рдкрджрдВрдбреЛрдВ рдХреЗ рд╕рд╛рде рд╕рд╢рд╕реНрддреНрд░ рдФрд░ рдЙрд╕реА рд╕рдордп рдЕрдиреБрд░реЛрдз рдХреЛ рд╕рд╣реЗрдЬрддреЗ рд╣реБрдП рдЬрд┐рд╕рдХреЗ рджреНрд╡рд╛рд░рд╛ рд╕рд░реНрд╡рд░ рдиреЗ рд╣рдореЗрдВ рдЗрд╕ рддрд░рд╣ рдЬрд╡рд╛рдм рджрд┐рдпрд╛, рд╣рдо рдХреИрдкреНрдЪрд╛ рдЗрдирдкреБрдЯ рдлрд╝рдВрдХреНрд╢рди рдХрд╣рддреЗ рд╣реИрдВ:
 [self getCaptcha]; 

рдЖрдЗрдП рдЗрд╕реЗ рдФрд░ рдЕрдзрд┐рдХ рд╡рд┐рд╕реНрддрд╛рд░ рд╕реЗ рд╡рд┐рдЪрд╛рд░ рдХрд░реЗрдВ:
 - (void) getCaptcha { NSString *captcha_img = [[NSUserDefaults standardUserDefaults] objectForKey:@"captcha_img"]; UIAlertView *myAlertView = [[UIAlertView alloc] initWithTitle:@" :\n\n\n\n\n" message:@"\n" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil]; UIImageView *imageView = [[[UIImageView alloc] initWithFrame:CGRectMake(12.0, 45.0, 130.0, 50.0)] autorelease]; imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:captcha_img]]]; [myAlertView addSubview:imageView]; UITextField *myTextField = [[[UITextField alloc] initWithFrame:CGRectMake(12.0, 110.0, 260.0, 25.0)] autorelease]; [myTextField setBackgroundColor:[UIColor whiteColor]]; //   myTextField.autocorrectionType = UITextAutocorrectionTypeNo; //   myTextField.autocapitalizationType = UITextAutocapitalizationTypeNone; myTextField.tag = 33; [myAlertView addSubview:myTextField]; [myAlertView show]; [myAlertView release]; } - (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { if(isCaptcha && buttonIndex == 1){ isCaptcha = NO; UITextField *myTextField = (UITextField *)[actionSheet viewWithTag:33]; [[NSUserDefaults standardUserDefaults] setObject:myTextField.text forKey:@"captcha_user"]; NSLog(@"Captcha entered: %@",myTextField.text); //           NSString *request = [[NSUserDefaults standardUserDefaults] objectForKey:@"request"]; NSDictionary *newRequestDict =[self sendRequest:request withCaptcha:YES]; NSString *errorMsg = [[newRequestDict objectForKey:@"error"] objectForKey:@"error_msg"]; if(errorMsg) { [self sendFailedWithError:errorMsg]; } else { [self sendSuccessWithMessage:@"     !"]; } } } 

UIImageView рдФрд░ UITextField рдФрд░ captcha_img рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рдЕрддрд┐рд░рд┐рдХреНрдд рдХреЗ рд╕рд╛рде, рдорд╛рдирдХ UIAlertView рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ, рд╣рдо рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рдХреИрдкреНрдЪрд╛ рджрд░реНрдЬ рдХрд░рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рджреЗрддреЗ рд╣реИрдВред рдХреИрдкреНрдЪрд╛ рджрд░реНрдЬ рдХрд┐рдП рдЬрд╛рдиреЗ рдХреЗ рдмрд╛рдж, UIAlertView рдкреНрд░рддрд┐рдирд┐рдзрд┐ рд╕рдорд╛рд░реЛрд╣ рдореЗрдВ, рдХреИрдкреНрдЪрд╛_рдпреВрдЬрд╝рд░ рдХреБрдВрдЬреА рдХреЗ рд╕рд╛рде NSUserDefaults рдореЗрдВ рджрд░реНрдЬ рдХрд┐рдП рдЧрдП рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреЛ рд╕рд╣реЗрдЬреЗрдВ рдФрд░ рдкрд╣рд▓реЗ рд╕реЗ рд╕рд╣реЗрдЬреЗ рдЧрдП рдЕрдиреБрд░реЛрдз url рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рдЗрд╕реЗ рдлрд┐рд░ рд╕реЗ рдХрд░реЗрдВ, рдЗрд╕ рдмрд╛рд░ рдкреИрд░рд╛рдореАрдЯрд░ рдореЗрдВ Captcha: YES рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВред рдкрд░рд┐рдгрд╛рдорд╕реНрд╡рд░реВрдк, рдЕрдиреБрд░реЛрдз рднреЗрдЬрдиреЗ рд╕реЗ рдкрд╣рд▓реЗ, рдЗрд╕рдореЗрдВ рдХреИрдкреНрдЪрд╛_рд╕рд┐рдб рдФрд░ рдХреИрдкреНрдЪрд╛_рдХреА рдкреИрд░рд╛рдореАрдЯрд░ рдЬреЛрдбрд╝реЗ рдЬрд╛рддреЗ рд╣реИрдВ (рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдиреЗ рдХреНрдпрд╛ рджрд░реНрдЬ рдХрд┐рдпрд╛ рд╣реИ):
 - (NSDictionary *) sendRequest:(NSString *)reqURl withCaptcha:(BOOL)captcha { //      ,      captcha_sid  captcha_key if(captcha == YES){ NSString *captcha_sid = [[NSUserDefaults standardUserDefaults] objectForKey:@"captcha_sid"]; NSString *captcha_user = [[NSUserDefaults standardUserDefaults] objectForKey:@"captcha_user"]; //      .  ,      . reqURl = [reqURl stringByAppendingFormat:@"&captcha_sid=%@&captcha_key=%@", captcha_sid, [self URLEncodedString: captcha_user]]; } ... 

рдХреИрдкреНрдЪрд╛ рджрд░реНрдЬ рдХрд┐рдпрд╛ рдЧрдпрд╛, рдЕрдиреБрд░реЛрдз рднреЗрдЬрд╛ рдЧрдпрд╛, рдкрд╛рда рдХреЛ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рджреАрд╡рд╛рд░ рдкрд░ рд╕рдлрд▓рддрд╛рдкреВрд░реНрд╡рдХ рдкреЛрд╕реНрдЯ рдХрд┐рдпрд╛ рдЬрд╛рдирд╛ рдЪрд╛рд╣рд┐рдП!

реи.реи рдПрдХ рджреАрд╡рд╛рд░ рдкрд░ рдПрдХ рдЫрд╡рд┐ рдкреЛрд╕реНрдЯ рдХрд░рдирд╛
рдЕрдХреНрд╕рд░ рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдХреА рджреАрд╡рд╛рд░ рдкрд░ рдПрдкреНрд▓рд┐рдХреЗрд╢рди рд╕реЗ рдПрдХ рдлреЛрдЯреЛ рд▓рдЧрд╛рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реЛрддреА рд╣реИред рдЗрд╕ рд╕рдорд╕реНрдпрд╛ рдХреЛ рд╣рд▓ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рдЖрдкрдХреЛ рдирд┐рдореНрди рдЪрд░рдгреЛрдВ рд╕реЗ рдЧреБрдЬрд░рдирд╛ рд╣реЛрдЧрд╛:
  1. рд╣рдорд╛рд░реА рдЫрд╡рд┐ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП VKontakte рд╕рд░реНрд╡рд░ рдХреЗ url рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░реЗрдВ ( photos.getWallUploadServer )
  2. рд╕рд░реНрд╡рд░ рдХреА рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдкреНрд░рд╛рдкреНрдд рд▓рд┐рдВрдХ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рддреЗ рд╣реБрдП, рд╣рдо POST рд╡рд┐рдзрд┐ рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЫрд╡рд┐ рднреЗрдЬрддреЗ рд╣реИрдВ
  3. рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рд╣реИрд╢, рдлреЛрдЯреЛ, рд╕рд░реНрд╡рд░ рдХреЛ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рджреАрд╡рд╛рд░ рдкрд░ рдлреЛрдЯреЛ рдХреЛ рдмрдЪрд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдХрдорд╛рдВрдб рднреЗрдЬреЗрдВрдЧреЗ (рдлреЛрдЯреЛред saveWallPhoto )
  4. рдкреНрд░рддрд┐рдХреНрд░рд┐рдпрд╛ рдореЗрдВ рдПрдХ рдлреЛрдЯреЛ рдЖрдИрдбреА рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдо рджреАрд╡рд╛рд░ рдкрд░ рдПрдХ рддрд╕реНрд╡реАрд░ рдкреЛрд╕реНрдЯ рдХрд░рдиреЗ рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░рддреЗ рд╣реИрдВред


2.2.1 рдЫрд╡рд┐ рдЕрдкрд▓реЛрдб рдХреЗ рд▓рд┐рдП рд╡реАрдХреЗ рд╕рд░реНрд╡рд░ рдпреВрдЖрд░рдПрд▓ рдкреНрд░рд╛рдкреНрдд рдХрд░рдирд╛
 - (IBAction)sendImageAction:(id)sender { if(!isAuth) return; UIImage *image = [UIImage imageNamed:@"test.jpg"]; NSString *user_id = [[NSUserDefaults standardUserDefaults] objectForKey:@"VKAccessUserId"]; NSString *accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"VKAccessToken"]; //  1 NSString *getWallUploadServer = [NSString stringWithFormat:@"https://api.vk.com/method/photos.getWallUploadServer?owner_id=%@&access_token=%@", user_id, accessToken]; NSDictionary *uploadServer = [self sendRequest:getWallUploadServer withCaptcha:NO]; //      NSString *upload_url = [[uploadServer objectForKey:@"response"] objectForKey:@"upload_url"]; ... 

рдЕрдм, рдЫрд╡рд┐ рдбрд╛рдЙрдирд▓реЛрдб рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рд▓рд┐рдВрдХ рдкреНрд░рд╛рдкреНрдд рдХрд░рдиреЗ рдХреЗ рдмрд╛рдж, рд╣рдореЗрдВ рд╕рдВрд▓рдЧреНрди рдЫрд╡рд┐ рдХреЗ рд╕рд╛рде рдПрдХ POST рдЕрдиреБрд░реЛрдз рдХрд░рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИред рдРрд╕рд╛ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдЫрд╡рд┐ рдХреЛ NSData рдореЗрдВ рд░реВрдкрд╛рдВрддрд░рд┐рдд рдХрд░реЗрдВ рдФрд░ рдлрд╝рдВрдХреНрд╢рди рдХрд╛ рдЙрдкрдпреЛрдЧ рдХрд░рдХреЗ рдЕрдиреБрд░реЛрдз рдмрдирд╛рдПрдВ
 [self sendPOSTRequest:upload_url withImageData:imageData]; 


реи.реи.реи рдПрдХ POST рдХрд╛ рдЕрдиреБрд░реЛрдз рдХрд░реЗрдВ
 ... //  2 //    NSData NSData *imageData = UIImageJPEGRepresentation(image, 1.0f); NSDictionary *postDictionary = [self sendPOSTRequest:upload_url withImageData:imageData]; //     hash, photo, server NSString *hash = [postDictionary objectForKey:@"hash"]; NSString *photo = [postDictionary objectForKey:@"photo"]; NSString *server = [postDictionary objectForKey:@"server"]; ... 

рдЖрдк рдЙрджрд╛рд╣рд░рдг рдореЗрдВ POST рдЕрдиреБрд░реЛрдз рдмрдирд╛рдиреЗ рд╡рд╛рд▓реЗ рдлрд╝рдВрдХреНрд╢рди рдХреЛ рджреЗрдЦ рд╕рдХрддреЗ рд╣реИрдВред

2.2.3 VKontakte рд╕рд░реНрд╡рд░ рдкрд░ рдлрд╝реЛрдЯреЛ рд╕рд╣реЗрдЬрдиреЗ рдХреЗ рд▓рд┐рдП рдПрдХ рдЕрдиреБрд░реЛрдз рдмрдирд╛рдПрдБ
 ... //  3 //        ,    id  NSString *saveWallPhoto = [NSString stringWithFormat:@"https://api.vk.com/method/photos.saveWallPhoto?owner_id=%@&access_token=%@&server=%@&photo=%@&hash=%@", user_id, accessToken,server,photo,hash]; NSDictionary *saveWallPhotoDict = [self sendRequest:saveWallPhoto withCaptcha:NO]; NSDictionary *photoDict = [[saveWallPhotoDict objectForKey:@"response"] lastObject]; NSString *photoId = [photoDict objectForKey:@"id"]; ... 

рдЬрд╡рд╛рдм рдореЗрдВ, рд╣рдореЗрдВ рдбрд╛рдЙрдирд▓реЛрдб рдХрд┐рдП рдЧрдП рдлреЛрдЯреЛ рдХреА рдлреЛрдЯреЛ рдЖрдИрдбреА рдорд┐рд▓рддреА рд╣реИ, рдЕрдм рдпрд╣ рд╕рд╛рдорд╛рдиреНрдп рджреАрд╡рд╛рд░ рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП рдмрдиреА рд╣реБрдИ рд╣реИред рдкреЛрд╕реНрдЯ рдЕрдиреБрд░реЛрдз, рдЬрд╣рд╛рдВ рдЕрдиреБрд▓рдЧреНрдирдХ рдкреИрд░рд╛рдореАрдЯрд░ рдХреЗ рд░реВрдк рдореЗрдВ, рдлреЛрдЯреЛ рдЖрдИрдбреА рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВред рдпрджрд┐ рдЖрдкрдХреЛ рдЕрднреА рднреА рдПрдХ рд▓рд┐рдВрдХ рдЬреЛрдбрд╝рдиреЗ рдХреА рдЖрд╡рд╢реНрдпрдХрддрд╛ рд╣реИ, рддреЛ рдлреЛрдЯреЛ рдЖрдИрдбреА рдХреЗ рдмрд╛рдж рдпрд╣ рдкрд░реНрдпрд╛рдкреНрдд рд╣реИ, рдЗрд╕реЗ рдЕрд▓реНрдкрд╡рд┐рд░рд╛рдо рдХреЗ рд╕рд╛рде рдирд┐рд░реНрджрд┐рд╖реНрдЯ рдХрд░реЗрдВред

реи.реи.рек рджреАрд╡рд╛рд░ рдкрд░ рдлреЛрдЯреЛ рд▓рдЧрд╛рдПрдВ
 ... //  4 //      NSString *postToWallLink = [NSString stringWithFormat:@"https://api.vk.com/method/wall.post?owner_id=%@&access_token=%@&message=%@&attachment=%@", user_id, accessToken, [self URLEncodedString:@"      "], photoId]; NSDictionary *postToWallDict = [self sendRequest:postToWallLink withCaptcha:NO]; NSString *errorMsg = [[postToWallDict objectForKey:@"error"] objectForKey:@"error_msg"]; if(errorMsg) { [self sendFailedWithError:errorMsg]; } else { [self sendSuccessWithMessage:@"   !"]; } // !     ! 


рднрд╛рдЧ 3. рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рд▓реЙрдЧрдЖрдЙрдЯ
рд▓реЙрдЧрдЖрдЙрдЯ рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП, рдмрд╕ VKontakte рд╕рд░реНрд╡рд░ рдХреЛ рдПрдХ рдЕрдиреБрд░реЛрдз рднреЗрдЬреЗрдВ:
 NSString *logout = @"http://api.vk.com/oauth/logout"; 

рдЙрджрд╛рд╣рд░рдг рд▓реЙрдЧрдЖрдЙрдЯ рдлрд╝рдВрдХреНрд╢рди:
 - (IBAction)logout:(id)sender { //   logout NSString *logout = @"http://api.vk.com/oauth/logout"; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:logout] cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0]; NSData *responseData = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil]; if(responseData){ NSDictionary *dict = [[JSONDecoder decoder] parseJSONData:responseData]; NSLog(@"Logout: %@", dict); //    ,    isAuth = NO; [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"VKAccessUserId"]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"VKAccessToken"]; [[NSUserDefaults standardUserDefaults] removeObjectForKey:@"VKAccessTokenDate"]; [[NSUserDefaults standardUserDefaults] synchronize]; [self sendSuccessWithMessage:@"  !"]; } } 


рдЗрд╕ рддрдереНрдп рдХреЗ рдмрд╛рд╡рдЬреВрдж рдХрд┐ VKontakte рдПрдХ рддреНрд░реБрдЯрд┐ рдХреЗ рд╕рд╛рде рдЬрд╡рд╛рдм рджреЗрддрд╛ рд╣реИ, рдЙрдкрдпреЛрдЧрдХрд░реНрддрд╛ рдЕрднреА рднреА рдмрд╛рд╣рд░ рдирд┐рдХрд▓рддрд╛ рд╣реИ :)
 Logout: { error = "invalid_client"; "error_description" = "client_id is incorrect"; } 


рдирд┐рд╖реНрдХрд░реНрд╖
рдореБрдЭреЗ рдЙрдореНрдореАрдж рд╣реИ рдХрд┐ рдпрд╣ рд▓реЗрдЦ рдЖрдкрдХреЛ Vkontakte API рд╕реАрдЦрдиреЗ рдореЗрдВ рдорджрдж рдХрд░рддрд╛ рд╣реИред рдореБрдЭреЗ рдЯрд┐рдкреНрдкрдгреА, рдкрд░рд┐рд╡рд░реНрдзрди рдХреА рдЦреБрд╢реА рд╣реЛрдЧреАред

Source: https://habr.com/ru/post/In133504/


All Articles