Difference between revisions of "macOS NSURLConnection"
(→macOS NSURLConnection: New macOS content) |
m (→Retrieving data synchronously: Tweak formatting) |
||
Line 23: | Line 23: | ||
If the request succeeds, the contents of the request are returned as an NSData object and an NSURLResponse object for the request is returned by reference. If NSURLConnection is unable to retrieve the URL, the method returns nil and any available NSError instance by reference in the appropriate parameter. | If the request succeeds, the contents of the request are returned as an NSData object and an NSURLResponse object for the request is returned by reference. If NSURLConnection is unable to retrieve the URL, the method returns nil and any available NSError instance by reference in the appropriate parameter. | ||
− | If the request requires authentication to make the connection, valid credentials must already be available in the NSURLCredentialStorage object or must be provided as part of the requested URL. If the credentials are not available or fail to authenticate, the URL loading system responds by sending the NSURLProtocol subclass handling the connection a continueWithoutCredentialForAuthenticationChallenge: message. | + | If the request requires authentication to make the connection, valid credentials must already be available in the NSURLCredentialStorage object or must be provided as part of the requested URL. If the credentials are not available or fail to authenticate, the URL loading system responds by sending the NSURLProtocol subclass handling the connection a ''continueWithoutCredentialForAuthenticationChallenge:'' message. |
When a synchronous connection attempt encounters a server redirect, the redirect is always honored. Likewise, the response data is stored in the cache according to the default support provided by the protocol implementation. | When a synchronous connection attempt encounters a server redirect, the redirect is always honored. Likewise, the response data is stored in the cache according to the default support provided by the protocol implementation. | ||
Revision as of 01:29, 15 August 2020
│ English (en) │
This article applies to macOS only.
See also: Multiplatform Programming Guide
Overview
An NSURLConnection object lets you load the contents of a URL by providing a URL request object. The interface for NSURLConnection is sparse, providing only the controls to start and cancel asynchronous loads of a URL request. You perform most of your configuration on the URL request object itself.
NSURLConnection is available from macOS 10.2 onwards. As with many things Apple, be warned that this API was deprecated in 10.11 (El Capitan). Nonetheless, to paraphrase WWDC 2015 "Yeah, NSURLConnection is deprecated in 10.11, but it's not going away and will still work, but new features will be added to NSURLSession".
Creating a connection
The NSURLConnection class supports three ways of retrieving the content of a URL: synchronously, asynchronously using a completion handler block, and asynchronously using a custom delegate object.
Retrieving data synchronously
The NSURLConnection class provides support for retrieving the contents of a resource represented by an NSURLRequest object in a synchronous manner using the class method sendSynchronousRequest:returningResponse:error:. Using this method is not generally recommended, because it has severe limitations:
- Unless you are writing a command-line tool, you should add additional code to ensure that the request does not run on your application's main thread because it will block any user interaction until the data has been received.
- Minimal support is provided for requests that require authentication.
- There is no means of modifying the default behavior of response caching or accepting server redirects.
If the request succeeds, the contents of the request are returned as an NSData object and an NSURLResponse object for the request is returned by reference. If NSURLConnection is unable to retrieve the URL, the method returns nil and any available NSError instance by reference in the appropriate parameter.
If the request requires authentication to make the connection, valid credentials must already be available in the NSURLCredentialStorage object or must be provided as part of the requested URL. If the credentials are not available or fail to authenticate, the URL loading system responds by sending the NSURLProtocol subclass handling the connection a continueWithoutCredentialForAuthenticationChallenge: message. When a synchronous connection attempt encounters a server redirect, the redirect is always honored. Likewise, the response data is stored in the cache according to the default support provided by the protocol implementation.
Example code
unit Unit1;
{$mode objfpc}{$H+}
{$modeswitch objectivec1}
{$linkframework foundation}
interface
uses
Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls,
fphttpclient, CocoaAll, CocoaUtils
{$IF FPC_FULLVERSION >= 30200}
, OpenSSLSockets
{$endif}
;
{ TForm1 }
type
TForm1 = class(TForm)
Button1: TButton;
procedure Button1Click(Sender: TObject);
private
public
end;
var
Form1: TForm1;
implementation
{$R *.lfm}
procedure TForm1.Button2Click(Sender: TObject);
var
URL: NSURL;
urlData : NSData;
urlRequest : NSUrlRequest;
urlResponse: NSURLResponse;
urlConnection: NSURLConnection;
error: NSError;
urlBody: NSString;
begin
// create URL
URL := NSURL.URLWithString(NSSTR(PAnsiChar('https://sentinel.sentry.org/')));
if(Url = Nil) then
ShowMessage('NSURL.URLWithString failed!');
// create NSURLRequest object
urlRequest := NSURLRequest.requestWithURL(URL);
// create connection to retrieve URL
urlConnection := NSURLConnection.alloc.init;
urlData := urlConnection.sendSynchronousRequest_returningResponse_error(
urlRequest,
@urlResponse,
@error
);
// housekeeping
urlConnection.release;
// check for failure
if(urlData = Nil) then
begin
//NSLog(NSStr('Error in urlConnection: %@'), error);
ShowMessage('Error retrieving ' + NSSTringToString(URL.description)
+ LineEnding + NSStringToString(error.localizedDescription));
end
// otherwise success
else
begin
// show web page meta data
ShowMessage(NSStringToString(urlResponse.description));
// show web page content as hexadecimal
ShowMessage(NSStringToString(urlData.description));
// show web page content as HTML text
urlBody := NSString.alloc.initWithData(urlData,NSUTF8StringEncoding);
ShowMessage(NSStringToString(urlBody));
// housekeeping
urlBody.release;
end;
end;
end.
To compile the above code successfully you are going to have to add the missing initWithData function to the NSString class by editing /usr/local/share/fpcsrc/fpc-[3.0.4|3.2.0|3.3.1]/packages/cocoaint/src/foundation/NSString.inc to add the missing (highlighted) function as follows:
--- NSString.inc (revision 45778)
+++ NSString.inc (working copy)
@@ -105,6 +105,7 @@
function characterAtIndex (index: NSUInteger): unichar; message 'characterAtIndex:';
function init: instancetype; message 'init'; { NS_DESIGNATED_INITIALIZER }
function initWithCoder (aDecoder: NSCoder): instancetype; message 'initWithCoder:'; { NS_DESIGNATED_INITIALIZER }
+ function initWithData(data: NSData; encoding: NSStringEncoding) : instancetype; message 'initWithData:encoding:';
{ Adopted protocols }
function copyWithZone (zone: NSZonePtr): id; message 'copyWithZone:';
and then recompile the FPC source. This has been tested with FPC 3.0.4, FPC 3.2.0 and FPC 3.3.1. Note that for FPC 3.0.4 you need to replace "instancetype" in the highlighted line with "id"
I use the following script (for FPC 3.3.1; substitute your FPC version numbers as appropriate) to recompile FPC:
#!/bin/sh
cd /usr/local/share/fpcsrc/fpc-3.3.1/
make clean all FPC=/usr/local/lib/fpc/3.3.1/ppcx64 OS_TARGET=darwin CPU_TARGET=x86_64 OPT="-XR/Library/Developer/CommandLineTools/SDKs/MacOSX.sdk/"
make install FPC=/usr/local/lib/fpc/3.3.1/ppcx64 OS_TARGET=darwin CPU_TARGET=x86_64
- Note 1: The highlighted line(s) above should be all on one line.
- Note 2: You will almost certainly have to use sudo to execute that script successfully or face permissions problems.
Retrieving data asynchronously using a completion handler block
Under construction.
Retrieving data asynchronously using a custom delegate object
Under construction.