Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Locked thread
eschaton
Mar 7, 2007

Don't you just hate when you wind up in a store with people who are in a socioeconomic class that is pretty obviously about two levels lower than your own?

Huckleduck posted:

Quick question about using Swift as a script. I made an XCode project file with the Swift Package Manager. The purpose of the script is to contact a server and download some files, then write those files to disk. This is an async operation, but scripts end whenever they let go of the main thread. I've tried three things, one of which worked.

1. I tried to make a Dispatch Semaphor (a counting one, value of 0) and iterated it in the completion block of my async call in the script. This did not work, somehow the completion block never came back.
2. I tried using Dispatch Group. I made a group, entered the group, all the usual jazz, left the group in the completion block of the script and made a dispatch wait with a timeout. The timeout always gets hit, the completion group never comes back.
3. I made a property called "isDone" outside the function, setting it to false. Inside the async function's completion block I set it to true. Then, I grabbed the current runloop, then made an autorelease pool. In the autorelease pool I have a while loop that does nothing, but it does hold onto the main thread until isDone is true. This actually works. :how:

I realize that #3 here is jank, and in my defense I did #1 and #2 first - I have worked with GCD and am 95% sure I have all the elements in place. Is it not working because of the weirdness of running this script through Terminal?

For a classic command line tool with a main run loop, you'd run it repeatedly until the work is done, which would likely be signaled by a variable being set (in a thread-safe manner) by whatever the worker is, and then stopping the main run loop. The main run loop would check the variable (also in a thread-safe manner, of course) and then when it's set decide to stop running. Note that you can't rely on a run loop to stop on its own; the frameworks can add their own sources too, after all.

I strongly suspect that whatever mechanism you used to do the download relied on having the main run loop turning, in which case the above sounds like what you should do too. Your #3 is very close to it, you just need to set the Boolean safely, check it safely, actually run the main run loop, and explicitly stop the main run loop after setting the Boolean. This should all also be easy to encapsulate.

Adbot
ADBOT LOVES YOU

Doctor w-rw-rw-
Jun 24, 2008
Worth adding that, IIRC, background queues get to run before dispatch_main() is called, but the main thread does not, until libdispatch is entered via dispatch_main, CFRunLoopRun, or {UI,NS}ApplicationMain.

I think the pure libdispatch method is to use dispatch_main() and atexit() for cleanup, and call exit() with your exit code (correct me if I'm wrong).

Depending on your script, you can also make things a little nicer if you like by using dispatch sources to respond to signals, accept stdin input, or track file updates, and other cool stuff. You can make it so that cancelling a dispatch source triggers said call to exit(). An empty while loop can easily consume tons of unnecessary CPU cycles, so if it fits the use-case, you can have a pretty low overhead process by using the loop functions that already exist.

Doh004
Apr 22, 2007

Mmmmm Donuts...

Moogs posted:

So this is a stupid noob question, but I'm a stupid noob... when I'm making an iMessage extension, how do I control what it looks like when it's half screen (like when you have Messages open and hit the app button to switch to it) and when it's full screen? I think the answer is view controllers, is that right?

We made an iMessage application back for the iOS 10 launch: https://itunes.apple.com/us/app/plated-dinner-recipes-ingredients/id954364666?mt=8

Have it operate like any other application, except what would normally be your "UIApplicationDelegate" is the "MSMessagesAppViewController". You'll want to respond to the "willTransition(to presentationStyle: MSMessagesAppPresentationStyle)" and "didTransition(to presentationStyle: MSMessagesAppPresentationStyle)" delegate methods accordingly.

And yes, we used a storyboard to handle these flows.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice

Huckleduck posted:

Quick question about using Swift as a script. I made an XCode project file with the Swift Package Manager. The purpose of the script is to contact a server and download some files, then write those files to disk. This is an async operation, but scripts end whenever they let go of the main thread. I've tried three things, one of which worked.

1. I tried to make a Dispatch Semaphor (a counting one, value of 0) and iterated it in the completion block of my async call in the script. This did not work, somehow the completion block never came back.
2. I tried using Dispatch Group. I made a group, entered the group, all the usual jazz, left the group in the completion block of the script and made a dispatch wait with a timeout. The timeout always gets hit, the completion group never comes back.
3. I made a property called "isDone" outside the function, setting it to false. Inside the async function's completion block I set it to true. Then, I grabbed the current runloop, then made an autorelease pool. In the autorelease pool I have a while loop that does nothing, but it does hold onto the main thread until isDone is true. This actually works. :how:

I realize that #3 here is jank, and in my defense I did #1 and #2 first - I have worked with GCD and am 95% sure I have all the elements in place. Is it not working because of the weirdness of running this script through Terminal?

As others have said, you need to run the main runloop. Create a dispatch source signal handler for SIGINT so if the user presses CTRL+C you can cleanup properly. You don't need to bother freeing memory or anything fancy because the process will die shortly anyway, but it is nice to remove any temporary files, etc.

code:
let source = DispatchSource.makeSignalSource(signal: SIGINT)
source.setEventHandler {
    // Do cleanup, cancel, teardown work here
    print("\nExiting...")
    exit(0)
}
signal(SIGINT, SIG_IGN) //ignore default handler
source.resume()

// Do async work here

// Will never return
RunLoop.main.run()

Huckleduck
May 20, 2007
giving you the hucklebuck
Thanks for the tips.

Rudest Buddhist
May 26, 2005

You only lose what you cling to, bitch.
Fun Shoe
Is it just me or are Playgrounds slow / sometimes completely broken in 8.3.1?

Kallikrates
Jul 7, 2002
Pro Lurker

Rudest Buddhist posted:

Is it just me or are Playgrounds slow / sometimes completely broken in 8.3.1?

Playgrounds haven't had inline errors for me for several releases. The code/run/output cycle isn't any faster these days than running an app/tests. Maybe I need to nuke my Xcode.

Rudest Buddhist
May 26, 2005

You only lose what you cling to, bitch.
Fun Shoe
I got hit with the no inline errors thing on this last update also.

My issue is that after one compile the playground just runs indefinitely without giving me any output. I can even change the entire thing to 'let words = "hello"; print(words)' and I get nothing back. Running manually doesn't help either.

I guess I'll file a radar, but it's pretty broad. I have other XCode windows open (with full apps) while I'm in the playground. Maybe that's part of it...

eschaton
Mar 7, 2007

Don't you just hate when you wind up in a store with people who are in a socioeconomic class that is pretty obviously about two levels lower than your own?

Kallikrates posted:

Playgrounds haven't had inline errors for me for several releases. The code/run/output cycle isn't any faster these days than running an app/tests. Maybe I need to nuke my Xcode.

Reinstalling Xcode is virtually never going to help anything. (Same with reinstalling the operating system.)

Why is it even on peoples' list of things to try? You'd be better off trying the same thing under a brand new user account, in case there's some cached state interfering.

Kallikrates
Jul 7, 2002
Pro Lurker
I didn't really uninstall Xcode. It was just a hot take about trying to get Xcode into some working known default state. I generally have pretty good Swift code completion and highlighting compared to most people I talk to that write swift daily. I am just very surprised at how Playgrounds have regressed.

Rudest Buddhist
May 26, 2005

You only lose what you cling to, bitch.
Fun Shoe
I didn't realize how much I like and use playgrounds until they took a dump on me with this last update :(

Doctor w-rw-rw-
Jun 24, 2008
Is there an elegant abstraction for me to wrap lines of code to check errors in debug mode that will be compiled out zero cost in release mode? Specifically I'm using a rather stateful API with a geterror function that returns an error code, and I want to wrap every call to that API with something that will check for and log errors in debug mode, but get compiled out.

I currently have something like this:
Swift code:
func debug(file: String = #file, line: Int = #line, column: Int = #column, function: String = #function, statement: () -> Void) {
  statement()
  ...
  (log stuff here)
}
but that doesn't cover that blocks that return, blocks that throw, or both, and I presume that the code gets bloated tremendously, along with the compiler's ability to reason about it..

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Swift code:
func debug<T>(..., statement: () throws -> T) rethrows {
  let result = try statement()
  ...
  return result
}
It should compile away in optimized builds.

Doctor w-rw-rw-
Jun 24, 2008
Why is it so hard to turn an array of strings into a char** in Swift? :/

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Swift 4 trip report: updating 10k lines of Swift to compile without warnings as Swift 3.0, 3.1, 3.2 and 4.0 took about 4 hours and involves 12 #if swift(...) checks, most of which are for XCTest changes rather than Swift itself. Definitely the least painful migration by a huge margin (and the first time we've been able to reasonably support two major versions on a single code base).

Glimm
Jul 27, 2005

Time is only gonna pass you by

Should I be able to replace Cocoapods/Carthage with Swift Package Manager once Xcode 9 is released?

I haven't looked into SPM in awhile, last I remember it didn't work with iOS at all and maybe not with Objective-C laden libraries.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
SPM 4 still only supports macOS.

The last time I poked it at it, it appeared that being able to set the C++ version was the only hard blocker for us being able to support a spm package so I would expect most obj-c libraries to work in theory.

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do

Glimm posted:

I haven't looked into SPM in awhile, last I remember it didn't work with iOS at all

I...have missed that every time I've looked at it. That's an utter deal breaker. Are there plans to make SPM the sort of thing that can actually replace everything else? Carthage, after all, must be destroyed.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
Everything I can think of is on the roadmap with the possible exception of iOS support, which might not be an explicit goal but certainly seems to be am implicit goal.

Doh004
Apr 22, 2007

Mmmmm Donuts...
Uhh, why?

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Doh004 posted:

Uhh, why?

I just meant I don't remember seeing anyone say "SPM will for sure support iOS and it'll happen on this date". But I do remember seeing more broad "we want to support all platforms where Swift officially runs" statements.

Kallikrates
Jul 7, 2002
Pro Lurker
This requires a lot of optimism, building iOS apps is much more than a compiler and dependencies. See recent kerfuffle about swift-stdlib-tool none the less packaging.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
I always assumed that iOS support was on the roadmap once they had all the core functionality working because no one actually writes macOS applications anymore so why would you waste time building a macOS-only package manager? I guess if the actual goal is to use it to build macOS itself (and the bundled applications) it'd make sense.

dizzywhip
Dec 23, 2005

My understanding is that the initial goal has been to support server-side Swift, primarily on Linux. I’m certainly looking forward to the day it can be properly used for apps though.

Moogs
Jan 25, 2004

Proceeds the Weedian... Nazareth
I'm very new to development, so I'm probably using some wrong terms here, but I'm am trying to make an iMessage app with essentially three separate views -- compact (first image, when App is as big as they keyboard), expanded (second image) and a different view when the user touches a message (third image).



I'm trying to change didBecomeActive to account for the possible states... is this the right approach? Am I making any drat sense?

code:

    override func didBecomeActive(with conversation: MSConversation) {

        let presentationStyle: MSMessagesAppPresentationStyle
        
        if presentationStyle == compact { // how do I check the current presentationStyle?
            presentVC(presentationStyle: .compact, for: conversation)
        } else {
            presentVC(presentationStyle: .expanded, for: conversation)
        }
        
    }

eschaton
Mar 7, 2007

Don't you just hate when you wind up in a store with people who are in a socioeconomic class that is pretty obviously about two levels lower than your own?
That's more of a UIKit framework question than a Swift language or tooling question, you might get more assistance in the Apple platform thread.

ulmont
Sep 15, 2010

IF I EVER MISS VOTING IN AN ELECTION (EVEN AMERICAN IDOL) ,OR HAVE UNPAID PARKING TICKETS, PLEASE TAKE AWAY MY FRANCHISE

eschaton posted:

That's more of a UIKit framework question than a Swift language or tooling question, you might get more assistance in the Apple platform thread.

That thread is over here, FYI:
https://forums.somethingawful.com/showthread.php?threadid=3400187&pagenumber=288#lastpost

Moogs
Jan 25, 2004

Proceeds the Weedian... Nazareth

eschaton posted:

That's more of a UIKit framework question than a Swift language or tooling question, you might get more assistance in the Apple platform thread.


Thanks guys, I'll take my question over there!

Kobayashi
Aug 13, 2004

by Nyc_Tattoo
So is Chris Lattner gonna go back to Apple??

Doctor w-rw-rw-
Jun 24, 2008
*crosses fingers* I hope he goes to Facebook.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Every time I try to do something with generics I end up wishing I was writing C++. Protocol constraints are nice in theory but I seem to inevitably waste hours trying to work around limitations of the type system.

Today's annoyance is that optionals of equatable types have operator == but are not equatable because there's no conditional protocol conformance.

brap
Aug 23, 2004

Grimey Drawer
Was there a technical tradeoff that the Swift team decided to take in not supporting that, or is it more of a "haven't gotten around to it/didn't think of it" type thing?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
I think it's in the generics manifesto, so it's a "the design we picked is really hard and will take years to implement" thing.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
It's "conditional conformances". We intended to implement it in Swift 4 and didn't quite finish. It'll probably be in 4.1.

TheReverend
Jun 21, 2005

I'm a Swift idiot and a functional programming idiot.

For the following, how would I use map or flatmap to print a list of all the cities in "usa"?
My apologies but I can't seem to figure it out.

code:
class Country {
    var countryName: String?
    var states: [State]?
}

class State {
    var stateName: String?
    var cities: [String]?
}

let newYork = State()
newYork.stateName = "New York"
newYork.cities = ["Albany", "NYC"]

let florida = State()
florida.stateName = "Florida"
florida.cities = ["Orlando", "Jacksonville", "Miami"]

let usa = Country()
usa.countryName = "United States Of America"
usa.states = [newYork, florida]

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
Haven't tried it but
Swift code:

usa.states.flatMap { $0.cities ?? [] }

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Also stop making things optional for no reason.

TheReverend
Jun 21, 2005

pokeyman posted:

Haven't tried it but
Swift code:
usa.states.flatMap { $0.cities ?? [] }


rjmccall posted:

Also stop making things optional for no reason.

Yeah, all this optional stuff is making it difficult.

This is just an abstraction of a problem I'm facing where the model objects contain obj-c NSArrays.
Would it be advisable then to not use .map and .flatmap functions when the data originates from obj-c and is nullable?

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

TheReverend posted:

Yeah, all this optional stuff is making it difficult.

This is just an abstraction of a problem I'm facing where the model objects contain obj-c NSArrays.
Would it be advisable then to not use .map and .flatmap functions when the data originates from obj-c and is nullable?

Coming from objc isn’t really the problem if the properties are helpfully modelled and annotated.

It’s quite possible that juggling optional arrays makes flatMap too painful. Partly this is due to both Array.flatMap and Optional.flatMap existing, which can confuse you the programmer and occasionally the compiler too.

There’s no shame in good ol' for loops if that’s the clearest way to model your problem. I like map and flatMap but it’s just one tool of many.

Adbot
ADBOT LOVES YOU

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Yeah, you can still do it with optionals, it just turns it from usa.states.flatMap { $0.cities } into something a little more complex/obscure.

But you should also be able to just declare the properties to be nonnull. IIRC, if you do that the bridging logic will automatically turn an unexpected nil return into an empty array.

  • Locked thread