6

I am trying to create a thread in swift and send two parameters. I create thread and this work:

let thread = NSThread(target:self, selector:"getData", object:nil)
thread.start()

But how to send parameters to my func getData? How to create object with parameters like this:

let params =...
let thread = NSThread(target:self, selector:"getData", object:params)
thread.start()

...

getData(username: String, password: String) {
    ...
}
jww
  • 97,681
  • 90
  • 411
  • 885
gellezzz
  • 1,165
  • 2
  • 12
  • 21
  • 3
    Use of `NSThread` in Cocoa is almost always wrong. (On iOS, it's "always wrong" rather than "almost always wrong.") Apple has a very good document explaining how to convert thread-based constructions to Cocoa's concurrency model (called GCD). https://developer.apple.com/library/ios/documentation/General/Conceptual/ConcurrencyProgrammingGuide/ThreadMigration/ThreadMigration.html#//apple_ref/doc/uid/TP40008091-CH105-SW1 – Rob Napier Oct 02 '14 at 14:22
  • @RobNapier NSThread as runloop that allows me to run it for ever. Do we have similar option in Swift using GCD? – Satyam Dec 02 '20 at 04:44
  • @Satyam I assume you mean "it is possible to run an NSRunLoop forever within an NSThread." You can do the same thing in Swift; the overlays are called RunLoop and Thread. GCD is intentionally designed not to work that way. See the linked document above for the intended replacement designs. GCD is not just "threads with a new syntax." It employs a different design pattern. If you want to use the RunLoop+Thread design pattern, that still fully exists in Swift, it's just generally discouraged (and has been since OS X 10.6). – Rob Napier Dec 02 '20 at 14:13

3 Answers3

13

Instead of using threads directly, you should be using Grand Central Dispatch. In this case you'd want to use dispatch_async to call getData on a background queue:

let username = ...
let password = ...

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue) {
    getData(username, password);
}

Keep in mind that if getData actually returns data then you'll have to handle that inside dispatch_async's closure:

let username = ...
let password = ...

let queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
dispatch_async(queue) {
    let someData = getData(username, password)
    /* do something with someData */
}

/* !! someData is NOT available here !! */

I highly recommend taking a look at Apple's Concurrency Programming Guide if you're going to be doing multithreaded / concurrent programming on iOS.

Mike S
  • 41,895
  • 11
  • 89
  • 84
  • what if I want the thread to do an ongoing task as long as the app is running (it's an app for Mac actually) is using dispatch still safe? or in my case I should make my own thread since the app could be running as long as the computer is turned on – JustADev Feb 26 '15 at 19:25
  • 1
    @OmarBizreh Sure. I'd suggest creating your own queue and running your task on there. I can only think of a few special cases where you might want an ongoing task like that though... you might want to take a look at [`dispatch_source`s](https://developer.apple.com/library/mac/documentation/General/Conceptual/ConcurrencyProgrammingGuide/GCDWorkQueues/GCDWorkQueues.html); I've found them to be a good fit when I'm tempted to create an ongoing task. There's a good intro to them [here](https://mikeash.com/pyblog/friday-qa-2009-09-11-intro-to-grand-central-dispatch-part-iii-dispatch-sources.html). – Mike S Feb 26 '15 at 19:38
  • Thanks a lot Mike, I'll take a look at dispatch_source. As for what I'm doing I am using a lib for Socket connections so I want the app to listen to incoming requests all the time, is there a better approach than having a loop and waiting for a connection? – JustADev Feb 26 '15 at 20:17
  • @OmarBizreh it really depends on how the socket lib is written, but dispatch_sources would typically be a good fit for that sort of thing. – Mike S Feb 26 '15 at 20:22
  • Thanks Mike, its actually somewhat like .Net where I have a Listen() function that will just wait for someone to connect. so I'm going to loop on that function and handle received requests alone. I'll be going with dispatch_sources. However I found this https://github.com/anpol/DispatchKit do you recommend a newbie in swift to start with libs or should I do them my self for the sake of learning? – JustADev Feb 26 '15 at 20:35
  • @OmarBizreh I haven't used DispatchKit myself so it's hard to say. I personally prefer to at least get familiar with things before deciding to use a library, but it's really just a matter of the way you learn I think. – Mike S Feb 27 '15 at 00:46
  • Good point you have there. Thanks for your help I'll take it from here. I really appreciate it. – JustADev Feb 27 '15 at 17:16
3

What about creating a class to hold your parameters?

class Params {
    username: String
    password: String
    init (#username: String, password: String) {
        self.username = username
        self.password = password
    }
}
// ...
let thread = NSThread(target:self, selector:"getData:", object:Params(username:"xyz", password:"abc")
thread.start()
// ...
func getData(params: Params) {
    // ...
}
Grimxn
  • 22,115
  • 10
  • 72
  • 85
  • 2
    This is the only option when using threads. I'd consider using dispatch_async for this though. – Eugene Oct 02 '14 at 13:23
3

Updated with Swift 5

Thread.detachNewThreadSelector(#selector(getData), toTarget: self, with: params)
func getData(params: Params) {
    // ...
}
Aakash Verma
  • 91
  • 1
  • 2
  • 5