macOS NSURLConnection: what changed
Revision 0 to 1. Removed lines have a minus sign; added lines have a plus sign.
Title: macOS NSURLConnection
| Old | New | Line | |
|---|---|---|---|
| 1 | + | ## Overview | |
| 2 | + | ||
| 3 | + | 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. | |
| 4 | + | ||
| 5 | + | NSURLConnection is available from macOS 10.2 onwards. As with many things Apple, be warned that many of the methods in this API were 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 [[macOS NSURLSession]]". | |
| 6 | + | ||
| 7 | + | ## Creating a connection | |
| 8 | + | ||
| 9 | + | 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. | |
| 10 | + | ||
| 11 | + | ### Retrieving data synchronously | |
| 12 | + | ||
| 13 | + | 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: | |
| 14 | + | ||
| 15 | + | - 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. | |
| 16 | + | ||
| 17 | + | - Minimal support is provided for requests that require authentication. | |
| 18 | + | ||
| 19 | + | - There is no means of modifying the default behavior of response caching or accepting server redirects. | |
| 20 | + | ||
| 21 | + | 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. | |
| 22 | + | ||
| 23 | + | 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. | |
| 24 | + | ||
| 25 | + | #### Code example | |
| 26 | + | ||
| 27 | + | ``` pascal | |
| 28 | + | unit Unit1; | |
| 29 | + | ||
| 30 | + | {$mode objfpc}{$H+} | |
| 31 | + | {$modeswitch objectivec1} | |
| 32 | + | {$linkframework foundation} | |
| 33 | + | ||
| 34 | + | interface | |
| 35 | + | ||
| 36 | + | uses | |
| 37 | + | Classes, SysUtils, Forms, Controls, Graphics, Dialogs, StdCtrls, | |
| 38 | + | CocoaAll, CocoaUtils; | |
| 39 | + | ||
| 40 | + | { TForm1 } | |
| 41 | + | ||
| 42 | + | type | |
| 43 | + | ||
| 44 | + | TForm1 = class(TForm) | |
| 45 | + | Button1: TButton; | |
| 46 | + | procedure Button1Click(Sender: TObject); | |
| 47 | + | private | |
| 48 | + | ||
| 49 | + | public | |
| 50 | + | ||
| 51 | + | end; | |
| 52 | + | ||
| 53 | + | var | |
| 54 | + | Form1: TForm1; | |
| 55 | + | ||
| 56 | + | implementation | |
| 57 | + | ||
| 58 | + | {$R *.lfm} | |
| 59 | + | ||
| 60 | + | procedure TForm1.Button1Click(Sender: TObject); | |
| 61 | + | var | |
| 62 | + | URL: NSURL; | |
| 63 | + | urlData : NSData; | |
| 64 | + | urlRequest : NSUrlRequest; | |
| 65 | + | urlResponse: NSURLResponse; | |
| 66 | + | urlConnection: NSURLConnection; | |
| 67 | + | error: NSError; | |
| 68 | + | urlBody: NSString; | |
| 69 | + | begin | |
| 70 | + | ||
| 71 | + | // create URL | |
| 72 | + | URL := NSURL.URLWithString(NSSTR(PAnsiChar('https://sentinel.sentry.org/'))); | |
| 73 | + | if(Url = Nil) then | |
| 74 | + | ShowMessage('NSURL.URLWithString failed!'); | |
| 75 | + | ||
| 76 | + | // create NSURLRequest | |
| 77 | + | urlRequest := NSURLRequest.requestWithURL(URL); | |
| 78 | + | ||
| 79 | + | // create NSURLConnection | |
| 80 | + | urlConnection := NSURLConnection.alloc.init; | |
| 81 | + | ||
| 82 | + | // make synchronous URL request | |
| 83 | + | urlData := urlConnection.sendSynchronousRequest_returningResponse_error( | |
| 84 | + | urlRequest, | |
| 85 | + | @urlResponse, | |
| 86 | + | @error | |
| 87 | + | ); | |
| 88 | + | ||
| 89 | + | // housekeeping | |
| 90 | + | urlConnection.release; | |
| 91 | + | ||
| 92 | + | // check for failure | |
| 93 | + | if(urlData = Nil) then | |
| 94 | + | begin | |
| 95 | + | //NSLog(NSStr('Error in urlConnection: %@'), error); | |
| 96 | + | ShowMessage('Error retrieving ' + NSSTringToString(URL.description) | |
| 97 | + | + LineEnding + NSStringToString(error.localizedDescription)); | |
| 98 | + | end | |
| 99 | + | // otherwise success | |
| 100 | + | else | |
| 101 | + | begin | |
| 102 | + | // show web page meta data | |
| 103 | + | ShowMessage(NSStringToString(urlResponse.description)); | |
| 104 | + | ||
| 105 | + | // show web page content as hexadecimal | |
| 106 | + | ShowMessage(NSStringToString(urlData.description)); | |
| 107 | + | ||
| 108 | + | // show web page content as HTML text | |
| 109 | + | urlBody := NSString.alloc.initWithData_encoding(urlData,NSUTF8StringEncoding); | |
| 110 | + | ShowMessage(NSStringToString(urlBody)); | |
| 111 | + | ||
| 112 | + | // housekeeping | |
| 113 | + | urlBody.release; | |
| 114 | + | end; | |
| 115 | + | end; | |
| 116 | + | ||
| 117 | + | end. | |
| 118 | + | ``` | |
| 119 | + | ||
| 120 | + | Full project source code is available from [SourceForge](https://sourceforge.net/p/lazarus-wiki-projects/code/ci/master/tree/laz_nsurlconnection/). | |
| 121 | + | ||
| 122 | + | ##### Compilation note | |
| 123 | + | ||
| 124 | + | To compile the above code successfully you are going to have to add the missing *initWithData_encoding* 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: | |
| 125 | + | ||
| 126 | + | ``` pascal | |
| 127 | + | --- NSString.inc (revision 45778) | |
| 128 | + | +++ NSString.inc (working copy) | |
| 129 | + | @@ -105,6 +105,7 @@ | |
| 130 | + | function characterAtIndex (index: NSUInteger): unichar; message 'characterAtIndex:'; | |
| 131 | + | function init: instancetype; message 'init'; { NS_DESIGNATED_INITIALIZER } | |
| 132 | + | function initWithCoder (aDecoder: NSCoder): instancetype; message 'initWithCoder:'; { NS_DESIGNATED_INITIALIZER } | |
| 133 | + | + function initWithData_encoding(data: NSData; encoding: NSStringEncoding) : instancetype; message 'initWithData:encoding:'; | |
| 134 | + | ||
| 135 | + | { Adopted protocols } | |
| 136 | + | function copyWithZone (zone: NSZonePtr): id; message 'copyWithZone:'; | |
| 137 | + | ``` | |
| 138 | + | ||
| 139 | + | 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" | |
| 140 | + | ||
| 141 | + | I use the following script (for FPC 3.3.1; substitute your FPC version numbers as appropriate) to recompile FPC: | |
| 142 | + | ||
| 143 | + | ``` sh | |
| 144 | + | #!/bin/sh | |
| 145 | + | cd /usr/local/share/fpcsrc/fpc-3.3.1/ | |
| 146 | + | 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/" | |
| 147 | + | make install FPC=$PWD/compiler/ppcx64 OS_TARGET=darwin CPU_TARGET=x86_64 | |
| 148 | + | ``` | |
| 149 | + | ||
| 150 | + | - Note 1: The highlighted line(s) above should be all on one line. | |
| 151 | + | - Note 2: You will almost certainly have to use *sudo* to execute that script successfully or face permissions problems. | |
| 152 | + | ||
| 153 | + | ### Retrieving data asynchronously using a completion handler block | |
| 154 | + | ||
| 155 | + | The NSURLConnection class provides support for retrieving the contents of a resource represented by an NSURLRequest object in an asynchronous manner and calling a block when results are returned or when an error or timeout occurs. To do this, you call the class method *sendAsynchronousRequest:queue:completionHandler:*, providing: | |
| 156 | + | ||
| 157 | + | - the request object, | |
| 158 | + | - a completion handler block, and | |
| 159 | + | - an NSOperation queue on which that block should run. | |
| 160 | + | ||
| 161 | + | When the request completes or an error occurs, the URL loading system calls that block with the result data or error information. If the request succeeds, the contents of the request are passed to the callback handler block as an NSData object and an NSURLResponse object for the request. If NSURLConnection is unable to retrieve the URL, an NSError object is passed as the third parameter. | |
| 162 | + | ||
| 163 | + | This method has two significant limitations: | |
| 164 | + | ||
| 165 | + | - There is minimal support for requests that require authentication. 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. | |
| 166 | + | ||
| 167 | + | - There is no means of modifying the default behaviour of response caching or accepting server redirects. When a 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. | |
| 168 | + | ||
| 169 | + | #### Code example | |
| 170 | + | ||
| 171 | + | Note: Due to the use of the cblocks feature, you must use at least version 3.2.0 of the Free Pascal Compiler to compile it successfully. | |
| 172 | + | ||
| 173 | + | ``` pascal | |
| 174 | + | unit Unit1; | |
| 175 | + | ||
| 176 | + | {$mode objfpc}{$H+} | |
| 177 | + | {$modeswitch objectivec1} | |
| 178 | + | {$modeswitch cblocks} | |
| 179 | + | {$linkframework foundation} | |
| 180 | + | ||
| 181 | + | interface | |
| 182 | + | ||
| 183 | + | uses | |
| 184 | + | SysUtils, Forms, Controls, Dialogs, StdCtrls, | |
| 185 | + | CocoaAll, CocoaUtils; | |
| 186 | + | ||
| 187 | + | { TForm1 } | |
| 188 | + | ||
| 189 | + | type | |
| 190 | + | // setup cBlock for completion handler | |
| 191 | + | tblock = reference to procedure(response: NSURLResponse; data: NSData; connectionError: NSError); cdecl; cblock; | |
| 192 | + | ||
| 193 | + | // redefine version from packages/cocoaint/src/foundation/NSURLConnection.inc | |
| 194 | + | NSURLConnectionQueuedLoading = objccategory external (NSURLConnection) | |
| 195 | + | class procedure sendAsynchronousRequest_queue_completionHandler(request: NSURLRequest; queue: NSOperationQueue; completionHandler: tBlock); message 'sendAsynchronousRequest:queue:completionHandler:'; | |
| 196 | + | end; | |
| 197 | + | ||
| 198 | + | TForm1 = class(TForm) | |
| 199 | + | Button1: TButton; | |
| 200 | + | procedure Button1Click(Sender: TObject); | |
| 201 | + | private | |
| 202 | + | ||
| 203 | + | public | |
| 204 | + | ||
| 205 | + | end; | |
| 206 | + | ||
| 207 | + | var | |
| 208 | + | Form1: TForm1; | |
| 209 | + | ||
| 210 | + | implementation | |
| 211 | + | ||
| 212 | + | {$R *.lfm} | |
| 213 | + | ||
| 214 | + | //{$DEFINE DEBUG} | |
| 215 | + | ||
| 216 | + | // Completion handler: Executed after URL has been retrieved or retrieval fails | |
| 217 | + | procedure myCompletionHandler(response: NSURLResponse; data: NSData; connectionError: NSError); | |
| 218 | + | begin | |
| 219 | + | {$IFDEF DEBUG} | |
| 220 | + | NSLog(NSStr('Completion handler called')); | |
| 221 | + | {$ENDIF} | |
| 222 | + | ||
| 223 | + | // if no error | |
| 224 | + | if((data.Length > 0) and (connectionError = Nil)) | |
| 225 | + | then | |
| 226 | + | begin | |
| 227 | + | ShowMessage('Data desc: ' + LineEnding + NSStringToString(data.description)); | |
| 228 | + | ShowMessage('Response: ' + LineEnding + NSStringToString(response.description)); | |
| 229 | + | ShowMessage('HTML: ' + LineEnding + NSStringToString(NSString.alloc.initWithData_encoding(data,NSUTF8StringEncoding))); | |
| 230 | + | end | |
| 231 | + | // o/w return error | |
| 232 | + | else | |
| 233 | + | begin | |
| 234 | + | ShowMessage('Data length: ' + IntToStr(data.length)); | |
| 235 | + | ShowMessage('Error description: ' + LineEnding + NSStringToString(connectionError.description)); | |
| 236 | + | ShowMessage('Error retrieving: ' + NSStringToString(connectionError.userInfo.valueForKey(NSErrorFailingUrlStringKey)) | |
| 237 | + | + LineEnding + LineEnding + 'Reason: ' + NSStringToString(connectionError.localizedDescription)); | |
| 238 | + | end; | |
| 239 | + | end; | |
| 240 | + | ||
| 241 | + | // Retrieve web page | |
| 242 | + | procedure TForm1.Button1Click(Sender: TObject); | |
| 243 | + | var | |
| 244 | + | URL: NSURL; | |
| 245 | + | urlRequest : NSUrlRequest; | |
| 246 | + | urlConnection: NSURLConnection; | |
| 247 | + | begin | |
| 248 | + | ||
| 249 | + | // create NSURL | |
| 250 | + | URL := NSURL.URLWithString(NSSTR(PAnsiChar('https://sentinel.sentry.org/'))); | |
| 251 | + | if(Url = Nil) then | |
| 252 | + | ShowMessage('NSURL.URLWithString failed!'); | |
| 253 | + | ||
| 254 | + | // create NSURLRequest | |
| 255 | + | urlRequest := NSURLRequest.requestWithURL(URL); | |
| 256 | + | ||
| 257 | + | // create NSURLConnection | |
| 258 | + | urlConnection := NSURLConnection.alloc.init; | |
| 259 | + | ||
| 260 | + | // make asynchronous URL connection request | |
| 261 | + | urlConnection.sendAsynchronousRequest_queue_completionHandler | |
| 262 | + | (urlRequest, NSoperationQueue.mainQueue, @myCompletionHandler); | |
| 263 | + | ||
| 264 | + | // housekeeping | |
| 265 | + | urlConnection.release; | |
| 266 | + | end; | |
| 267 | + | ||
| 268 | + | end. | |
| 269 | + | ``` | |
| 270 | + | ||
| 271 | + | Full project source code is available from [SourceForge](https://sourceforge.net/p/lazarus-wiki-projects/code/ci/master/tree/laz_nsurlconnection1/). | |
| 272 | + | ||
| 273 | + | ##### Compilation note | |
| 274 | + | ||
| 275 | + | See the previous Compilation note above. | |
| 276 | + | ||
| 277 | + | ### Retrieving data asynchronously using a custom delegate object | |
| 278 | + | ||
| 279 | + | The NSURLConnection class provides support for retrieving the contents of a resource represented by an NSURLRequest object in an asynchronous manner using a custom delegate object that implements at least the following delegate methods: | |
| 280 | + | ||
| 281 | + | - connection:didReceiveResponse:, | |
| 282 | + | - connection:didReceiveData:, | |
| 283 | + | - connection:didFailWithError:, and | |
| 284 | + | - connectionDidFinishLoading:. | |
| 285 | + | ||
| 286 | + | I have also implemented the *connectionWillCacheResponse* delegate method so that you can disable caching of the response which is handy when testing/debugging web page retrieval code. | |
| 287 | + | ||
| 288 | + | The supported delegate methods are defined in the *NSURLConnectionDelegate*, *NSURLConnectionDownloadDelegate*, and *NSURLConnectionDataDelegate* protocols. | |
| 289 | + | ||
| 290 | + | #### Code example | |
| 291 | + | ||
| 292 | + | ``` pascal | |
| 293 | + | unit Unit1; | |
| 294 | + | ||
| 295 | + | {$mode objfpc}{$H+} | |
| 296 | + | {$modeswitch objectivec1} | |
| 297 | + | {$linkframework foundation} | |
| 298 | + | ||
| 299 | + | interface | |
| 300 | + | ||
| 301 | + | uses | |
| 302 | + | Classes, SysUtils, Forms, Dialogs, StdCtrls, | |
| 303 | + | CocoaAll, CocoaUtils; | |
| 304 | + | ||
| 305 | + | type | |
| 306 | + | { TForm1 } | |
| 307 | + | TForm1 = class(TForm) | |
| 308 | + | Button1: TButton; | |
| 309 | + | procedure Button1Click(Sender: TObject); | |
| 310 | + | private | |
| 311 | + | ||
| 312 | + | public | |
| 313 | + | ||
| 314 | + | end; | |
| 315 | + | ||
| 316 | + | { TMyDelegate } | |
| 317 | + | TMyDelegate = objcclass(NSObject) | |
| 318 | + | private | |
| 319 | + | ||
| 320 | + | public | |
| 321 | + | procedure connection_didReceiveResponse (connection: NSURLConnection; response: NSURLResponse); | |
| 322 | + | message 'connection:didReceiveResponse:'; | |
| 323 | + | procedure connection_didReceiveData (connection: NSURLConnection; data: NSData); | |
| 324 | + | message 'connection:didReceiveData:'; | |
| 325 | + | function connection_willCacheResponse (connection: NSURLConnection; cachedResponse: NSCachedURLResponse): NSCachedURLResponse; | |
| 326 | + | message 'connection:willCacheResponse:'; | |
| 327 | + | procedure connectionDidFinishLoading (connection: NSURLConnection); | |
| 328 | + | message 'connectionDidFinishLoading:'; | |
| 329 | + | procedure connection_didFailWithError (connection: NSURLConnection; error: NSError); | |
| 330 | + | message 'connection:didFailWithError:'; | |
| 331 | + | end; | |
| 332 | + | ||
| 333 | + | //{$DEFINE DEBUG} // Uncomment to log to Console app | |
| 334 | + | ||
| 335 | + | var | |
| 336 | + | Form1: TForm1; | |
| 337 | + | responseData: NSMutableData; | |
| 338 | + | connDelegate: TMyDelegate; | |
| 339 | + | ||
| 340 | + | implementation | |
| 341 | + | ||
| 342 | + | {$R *.lfm} | |
| 343 | + | ||
| 344 | + | procedure TMyDelegate.connection_didReceiveResponse (connection: NSURLConnection; response: NSURLResponse); | |
| 345 | + | begin | |
| 346 | + | {$IFDEF DEBUG} | |
| 347 | + | NSLog(NSStr('didReceiveResponse')); | |
| 348 | + | {$ENDIF} | |
| 349 | + | ||
| 350 | + | // A response has been received, so initialize the response variable | |
| 351 | + | // so that we can append data to it in the didReceiveData method | |
| 352 | + | // Note: as this method is called each time there is a redirect, | |
| 353 | + | // reinitializing it also serves to clear it. | |
| 354 | + | responseData := NSMutableData.alloc.init; | |
| 355 | + | end; | |
| 356 | + | ||
| 357 | + | procedure TMyDelegate.connection_didReceiveData (connection: NSURLConnection; data: NSData); | |
| 358 | + | begin | |
| 359 | + | {$IFDEF DEBUG} | |
| 360 | + | NSLog(NSStr('appendData')); | |
| 361 | + | {$ENDIF} | |
| 362 | + | ||
| 363 | + | // Append the new data to the response variable | |
| 364 | + | responseData.appendData(data); | |
| 365 | + | end; | |
| 366 | + | ||
| 367 | + | function TMyDelegate.connection_willCacheResponse (connection: NSURLConnection; cachedResponse: NSCachedURLResponse): NSCachedURLResponse; | |
| 368 | + | begin | |
| 369 | + | {$IFDEF DEBUG} | |
| 370 | + | NSLog(NSStr('willCacheResponse')); | |
| 371 | + | {$ENDIF} | |
| 372 | + | ||
| 373 | + | // Return nil to disable caching of the response for this connection | |
| 374 | + | Result := Nil; | |
| 375 | + | end; | |
| 376 | + | ||
| 377 | + | procedure TMyDelegate.connectionDidFinishLoading (connection: NSURLConnection); | |
| 378 | + | begin | |
| 379 | + | {$IFDEF DEBUG} | |
| 380 | + | NSLog(NSStr('didFinishLoading')); | |
| 381 | + | {$ENDIF} | |
| 382 | + | ||
| 383 | + | // The request is completed and data received, so show it | |
| 384 | + | ShowMessage(NSStringtoString(NSString.alloc.initWithData_encoding(responseData,NSUTF8StringEncoding))); | |
| 385 | + | end; | |
| 386 | + | ||
| 387 | + | procedure TMyDelegate.connection_didFailWithError (connection: NSURLConnection; error: NSError); | |
| 388 | + | begin | |
| 389 | + | {$IFDEF DEBUG} | |
| 390 | + | NSLog(NSStr('didFailWithError')); | |
| 391 | + | {$ENDIF} | |
| 392 | + | ||
| 393 | + | // The request failed | |
| 394 | + | ShowMessage('Request for ' + NSStringToString(error.userInfo.valueForKey(NSErrorFailingUrlStringKey)) + ' failed!' + LineEnding + LineEnding | |
| 395 | + | + 'Reason: ' + NSStringToString(error.localizedDescription)); | |
| 396 | + | end; | |
| 397 | + | ||
| 398 | + | procedure TForm1.Button1Click(Sender: TObject); | |
| 399 | + | var | |
| 400 | + | URL: NSURL; | |
| 401 | + | urlRequest : NSUrlRequest; | |
| 402 | + | urlConnection: NSURLConnection; | |
| 403 | + | begin | |
| 404 | + | {$IFDEF DEBUG} | |
| 405 | + | NSLog(NSStr('create url')); | |
| 406 | + | {$ENDIF} | |
| 407 | + | ||
| 408 | + | // create URL | |
| 409 | + | URL := NSURL.URLWithString(NSSTR(PAnsiChar('https://sentinel.sentry.org/'))); | |
| 410 | + | if(Url = Nil) then | |
| 411 | + | ShowMessage('NSURL.URLWithString failed!'); | |
| 412 | + | ||
| 413 | + | {$IFDEF DEBUG} | |
| 414 | + | NSLog(NSStr('create request')); | |
| 415 | + | {$ENDIF} | |
| 416 | + | ||
| 417 | + | // create NSURLRequest | |
| 418 | + | urlRequest := NSURLRequest.requestWithURL(URL); | |
| 419 | + | ||
| 420 | + | {$IFDEF DEBUG} | |
| 421 | + | NSLog(NSStr('create connection delegate')); | |
| 422 | + | {$ENDIF} | |
| 423 | + | ||
| 424 | + | // create connection delegate | |
| 425 | + | connDelegate := TMyDelegate.alloc.init; | |
| 426 | + | ||
| 427 | + | {$IFDEF DEBUG} | |
| 428 | + | NSLog(NSStr('create connection and fire request')); | |
| 429 | + | {$ENDIF} | |
| 430 | + | ||
| 431 | + | // create NSURLConnection and make request | |
| 432 | + | urlConnection := NSURLConnection.alloc.initWithRequest_delegate(urlRequest, connDelegate); | |
| 433 | + | ||
| 434 | + | {$IFDEF DEBUG} | |
| 435 | + | NSLog(NSStr('cleanup')); | |
| 436 | + | {$ENDIF} | |
| 437 | + | ||
| 438 | + | // housekeeping cleanup | |
| 439 | + | urlConnection.release; | |
| 440 | + | connDelegate.release; | |
| 441 | + | end; | |
| 442 | + | ||
| 443 | + | end. | |
| 444 | + | ``` | |
| 445 | + | ||
| 446 | + | Full project source code is available from [SourceForge](https://sourceforge.net/p/lazarus-wiki-projects/code/ci/master/tree/laz_nsurlconnection2/). | |
| 447 | + | ||
| 448 | + | ##### Compilation note | |
| 449 | + | ||
| 450 | + | See the previous Compilation note above. | |
| 451 | + | ||
| 452 | + | ## See also | |
| 453 | + | ||
| 454 | + | - [[macOS NSURLSession]] - the replacement for [[macOS NSURLConnection|NSURLConnection]]. | |
| 455 | + | - [[fpwebview]] - Free Pascal binding for webview, a cross-platform library that links Cocoa/WebKit on macOS. | |
| 456 | + | ||
| 457 | + | ## External links | |
| 458 | + | ||
| 459 | + | - [Apple: NSString](https://developer.apple.com/documentation/foundation/nsstring). | |
| 460 | + | - [Apple: NSURLConnection](https://developer.apple.com/documentation/foundation/nsurlconnection). | |
| 461 | + | - [Apple: NSURLRequest](https://developer.apple.com/documentation/foundation/nsurlrequest). | |
| 462 | + | - [Apple: NSData](https://developer.apple.com/documentation/foundation/nsdata). | |
| 463 | + | - [Apple: NSURL](https://developer.apple.com/documentation/foundation/nsurl). | |
| 464 | + | - [Apple: NSURLSession](https://developer.apple.com/documentation/foundation/nsurlsession). | |
| 465 | + | ||
| 466 | + | --- | |
| 467 | + | *From the Free Pascal wiki, page "macOS NSURLConnection", as it stood on 2022-02-21 after a change by Trev, out of the wiki's dump of 2024-05-26. Copyright stays with the author who wrote it, according to the old wiki's [[Licensing]] page. If you have concerns about this material, [message the admin](/wiki-contact).* |
