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.
 
  • Post
  • Reply
pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

prom candy posted:

So is it cool and good to just chuck this class underneath my ViewController class in the same file? I know in some languages that's not all that popular but it does seem like Xcode makes it a little easier to navigate long files. The more languages I learn the more I find I want to learn the the sort of style/housekeeping practices early on but a lot of tutorials don't really focus on that. The guy who started this project also uses 4 spaces for indenting so I'm suspicious about how much I want to trust his way of doing stuff (while obviously still trying to maintain consistency in the project)

It's just a style thing. Some people wanna stuff everything into a single main.swift, other people are allergic to files that don't fit on their monitor. Personally I don't enjoy having to change seventeen different files just to rework a single screen, but whatever works.

In this example I'd probably do something like
code:
class TwitterHandleSearchViewController {
    // blah blah

    let searchField = SearchField()

    class SearchField: UIView {
        // blah blah
    }
}
then it's very clear where the view is expected to be used. (This gets annoying with Interface Builder, which afaik can't find classes scoped like this. Hopefully I'm wrong about this but it stumped me last time I tried.)

Adbot
ADBOT LOVES YOU

prom candy
Dec 16, 2005

Only I may dance
Okay great, thanks! I'm probably going to be a pest in this thread while I get a handle on some of this stuff. Swift is a cool language though, I like it so far. I worked in an iOS app back in 2010 or so and that really turned me off of wanting to work on any more, but it seems like it's way nicer now.

brap
Aug 23, 2004

Grimey Drawer
I think one of the biggest things I’ve taken away after gaining some experience is that figuring out the right way to break your code up across files is not nearly as important as becoming very fluent in your IDE’s commands for code navigation.

Pulcinella
Feb 15, 2019
Probation
Can't post for 11 days!
Uhg learning new things and practicing is never not frustrating :argh::bang:.

I’m trying to learn Swift UI and things that that would take two seconds to set up with Autolayout in Interface Builder feel impossible in SwiftUI. Like im trying to place 4 small (10by10) square views in a parent view, one in each corner. This would be incredibly trivial in IB but feels impossible in SwiftUI. I’ve tried using a z stack and aligning the sub views inside but this just causes the z stack to collapse down (basically shrink wrap) the 4 sub views. (Also .overlay() feels weird for using parentheses instead of curly braces).

The visual editor doesn’t feel very helpful because I have to just hunt through a list for the various modifiers or view types and I end up doing it mostly in code.

The IB XML merge nightmare is gone but now view files are cluttered with stylizing code.

Sorry just needed to vent. The start of learning new things is always the most painful.

lord funk
Feb 16, 2004

Pulcinella posted:

Sorry just needed to vent. The start of learning new things is always the most painful.

Yeah one day I realized that doing all my layout in code means not having to go through growing pains every time the latest UI toolset comes along.

brand engager
Mar 23, 2011

Pulcinella posted:

Uhg learning new things and practicing is never not frustrating :argh::bang:.

I’m trying to learn Swift UI and things that that would take two seconds to set up with Autolayout in Interface Builder feel impossible in SwiftUI. Like im trying to place 4 small (10by10) square views in a parent view, one in each corner. This would be incredibly trivial in IB but feels impossible in SwiftUI. I’ve tried using a z stack and aligning the sub views inside but this just causes the z stack to collapse down (basically shrink wrap) the 4 sub views. (Also .overlay() feels weird for using parentheses instead of curly braces).

The visual editor doesn’t feel very helpful because I have to just hunt through a list for the various modifiers or view types and I end up doing it mostly in code.

The IB XML merge nightmare is gone but now view files are cluttered with stylizing code.

Sorry just needed to vent. The start of learning new things is always the most painful.

Something like?
code:
VStack {
    HStack {
        viewA //top left on left-to-right language phones
        Spacer()
        viewB //top right
    }
    Spacer()
    HStack {
        viewC //bottom left
        Spacer()
        viewD //bottom right
    }
}
and use padding() as needed

KidDynamite
Feb 11, 2005

brand engager posted:

Something like?
code:
VStack {
    HStack {
        viewA //top left on left-to-right language phones
        Spacer()
        viewB //top right
    }
    Spacer()
    HStack {
        viewC //bottom left
        Spacer()
        viewD //bottom right
    }
}
and use padding() as needed

This works if you're statically sizing the views but if they're dynamic then you're going to run into issues as Spacer() will only fill empty space.

brand engager
Mar 23, 2011

what do you mean statically sizing

Pulcinella
Feb 15, 2019
Probation
Can't post for 11 days!
I think something like:
code:
VStack {
    HStack {
        Rectangle().frame(10,10)
        Spacer()
        Rectangle().frame(10,10)
    }
    Spacer()
    HStack {
        Rectangle().frame(10,10)
        Spacer()
        Rectangle().frame(10,10)
    }
}
Which is more or less what I ended up doing. Depending on how dynamic you want to go I think I could also wrap the whole thing in a geometry reader if I wanted the rectangles to be a quarter of the width of the parent instead of a static 10.

SwiftUI views set their own size and can override their parent view’s suggestion though. It’s definitely awkward trying to do anything that can’t be easily expressed as a stack view, which is a lot, but not everything. We aren’t going to switch to SwiftUI any time soon at work (most clients still want to support back to iOS12 with some even earlier), but we still don’t know how we are going to tell our designers that we don’t know if a lot of their designs are going to work in the future.

I do like just being able to apply a gaussian blur to a view. Wish Apple would let us apply CIFilters to a CALayer on iOS (you can on macOS but on iOS the filters property in CALayer does nothing.)

prom candy
Dec 16, 2005

Only I may dance
So I'm building this subclass view inside my viewcontroller that I was posting about on Saturday and I'm wondering how to get the click event from the button inside the subview to trigger a function on my viewcontroller. my code is kinda like this

code:
class TwitterSearchController: UIViewController {
  let selectedAccountView = SelectedAccountView()
  let searchInput = UIInput()
  var selectedAccount: TwitterAccount?  {
    didSet {
      if let selectedAccount = selectedAccount {
         searchInput.isHidden = true
         selectedAccountView.isHidden = false
         selectedAccountView.username = selectedAccount.username
      } else {
         searchInput.isHidden = false
         selectedAccountView.isHidden = true 
         selectedAccountView.username = nil
      }
  }
  

  func clearSelectedAccount() {
    selectedAccount = nil
  }

  class SelectedAccountView: UIView {
    var username: String?
    private let twitterLogo = UIImageView()
    private let usernameLabel = UILabel()
    private let closeButton = UIButton()
    private let container = UIStackView(arrangedSubviews: [twitterLogo, usernameLabel, closeButton])

    // Do stuff to make this view look good
  } 
}
So what I want to have happen is when the user taps on the SelectedAccountView's closeButton, it fires the clearSelectedAccount func from the parent class. There are a couple ways I can think of to do this but I'm not sure which is right:

1. My React-brain says I should pass clearSelectedAccount as a param into SelectedAccountView when I initialize it. Like
pre:
let selectedAccountView = SelectedAccountView(onTapClose: clearSelectedAccount)
. I don't know if this is something that you can/should do in Swift though.

2. I could make TwitterSearchController the delegate of SelectedAccountView and have a function like selectedAccountView(tappedClose: ) but that feels a bit odd since it seems weird to have to use a delegate for something that's a subclass. Maybe I'm wrong there?

3. Forget about subclassing entirely and just manage this whole thing in TwitterSearchController. That doesn't feel like very good OOP though.

4. Maybe there's something where I can like .addTarget on SelectedAccountView and then have an .addTarget on the button inside which fires the class' addTarget?

I'm assuming there's just a correct/common way to do this, anyone know what it is?

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
Usual approach would be a delegate or passing in a block, you got it. Don't forget to take a weak reference to self if you pass a block in, otherwise you'll get a retain cycle.

prom candy
Dec 16, 2005

Only I may dance
Thanks!

prom candy
Dec 16, 2005

Only I may dance
Is it considered bad to put a lot of logic into a variable's didSet observer? I think I'm kind of trying to shoehorn declarative programming into ViewControllers, so I figured I could put a bunch of UI update code (hide this, show that, etc.) into the didSet of a variable, and then when anything changes it the view will update. Feels like that might be a bit of a footgun though?

I know SwiftUI works in a way that would probably be more familiar to me as a React developer but I also know a lot of people say it's not really ready for prime time and the guy who's running this project definitely doesn't want to use it.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
Not sure about bad form, but it gets complicated if you end up with many didSets. I usually end up making an update() method that ensures the view reflects all current state, then I call update() from the didSets (and anywhere else that needs it, like the end of the initializer maybe).

lord funk
Feb 16, 2004

Right. That falls under my general rule of: UI responders don't do anything but call functions that do stuff. Because inevitably that update needs to be triggered from four different sources.

prom candy
Dec 16, 2005

Only I may dance
The guy that I'm working with said that he wouldn't expect doing something like self.displayName = nil to update the UI but I just wanted to see if that was a common feeling among iOS devs. It sounds like maybe it's fine but just better if the actual code goes in a function that gets called by the didSet rather than straight in the didSet.

My thinking is I'd never want self.displayName to be nil but the UI to reflect something else (i.e. because someone set it to nil without explicitly running the update() function)

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
I would expect pretty well any method call or property change on a view to be reflected in the UI because that's the entire point of a view. Totally up to y'all how to expose the functionality, of course, and avoding surprising your teammates is a worthy goal.

Maybe it's not property setters, that's ok. Sometimes I make all properties private (or private(set)) and expose my one update() method that takes a parameter for each property. Then you literally can't call update() without specifying every bit of the view's state. Other times there's a viewmodel type that I'll watch for changes, or the didSets trigger an update() or setNeedsLayout() or setNeedsDisplay().

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Binding properties to the UI so that assignments to the property update the UI too are a very common thing on basically every platform. That doesn't necessarily mean that it's the best way to do things, but it's certainly not something that should surprise anyone who has ever touched GUI code before.

prom candy
Dec 16, 2005

Only I may dance
Does Swift have any kind of union types or type discrimination? I can't seem to find anything but maybe it's one of those things where they just call it something else? Here's a typescript example of what I mean:

code:
interface BaseVehicle {
  color: string;
  name: string;
  make: string;
  model: string;
}

interface Car extends BaseVehicle {
  hasPedals: false;
  pistons: number;
}

interface Bicycle extends BaseVehicle {
  hasPedals: true;
  tireType: 'slick' | 'knobby' | 'fat';
}

type Vehicle = Car | Bicycle;

function doSomethingWithAVehicle(vehicle: Vehicle) {
  // Vehicle could be a Car or a Bicycle here

  if (vehicle.hasPedals) {
    // Compiler knows that vehicle is a Bicycle in here
  } else {
    // Compiler knows that vehicle is a Car in here
  }
}
Does this concept exist in Swift?

Fate Accomplice
Nov 30, 2006




prom candy posted:

Does Swift have any kind of union types or type discrimination? I can't seem to find anything but maybe it's one of those things where they just call it something else? Here's a typescript example of what I mean:

Does this concept exist in Swift?

use a protocol and have your types implement it.

brap
Aug 23, 2004

Grimey Drawer
Seems like the closest analogue in swift is enums?

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
enum is as close as you'll get.

prom candy
Dec 16, 2005

Only I may dance
Thanks, that's kind of what I figured. I can live without it, it's just really convenient.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Enums can carry payload values, so they seem to be exactly what you want.

SaTaMaS
Apr 18, 2003
Has anyone done much unit testing with Core Data? I have some test files that each succeed individually, but when I try to run them all I get the error "Failed to find a unique match for an NSEntityDescription to a managed object subclass" as though the tests were creating multiple NSPersistentContainers (I'm only creating them in memory) at the same time and the entity names were colliding. These are all instance level NSPersistentContainer variable and since they're only in memory I'm not sure why they know about each other or how to fix it.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
Random guess: are you creating multiple instances of your managed object model?

SaTaMaS
Apr 18, 2003

pokeyman posted:

Random guess: are you creating multiple instances of your managed object model?

On each test case I initialize an NSPersistentContainer and loadPersistentStores in setUp and destroyPersistentStore and set the NSPersistentContainer to nil in tearDown

It looks like I'm creating multiple identical persistent stores somehow, but since each test file works individually. Multiple test files extend the same XCTestCase superclass I created for testing core data, but since the NSPersistentContainer is instance-level I'm not sure where the problem is

SaTaMaS fucked around with this message at 03:00 on Dec 2, 2020

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

SaTaMaS posted:

On each test case I initialize an NSPersistentContainer and loadPersistentStores in setUp and destroyPersistentStore and set the NSPersistentContainer to nil in tearDown

It looks like I'm creating multiple identical persistent stores somehow, but since each test file works individually. Multiple test files extend the same XCTestCase superclass I created for testing core data, but since the NSPersistentContainer is instance-level I'm not sure where the problem is

My guess is the first test loads the model, then the second test tries to load the same model again and you're hooped. Does it go away if you init a single NSManagedObjectModel (like at the module level, so there's only ever one instance) and pass it in to the NSPersistentContainer's initializer? Or you could make it a static var in your test case superclass, just make sure there's only ever one.

I could be barking up the wrong tree, but this is sounding awfully familiar, and that's how I got around it.

edit: yeah this https://stackoverflow.com/questions/51851485/multiple-nsentitydescriptions-claim-nsmanagedobject-subclass

TheReverend
Jun 21, 2005

Is there any reason future apps can't be developed on xcode 11 at this point ?

I know eventually it won't be supported, but for now it's ok, yeah ?

Glimm
Jul 27, 2005

Time is only gonna pass you by

TheReverend posted:

Is there any reason future apps can't be developed on xcode 11 at this point ?

I know eventually it won't be supported, but for now it's ok, yeah ?

I don't think there's an issue with that for now, I don't even know of an announcement for a sunset date (but I expect not to be able to use 11 in 2022).

That said, a terrible SDK I am forced to use has me making builds regularly with 11.1 and 11.3.1 (and switching between them). I can't wait until this poo poo dies. Also gently caress them for making a binary SDK using Swift that I've had to use since Xcode 9 and god dammit

Glimm
Jul 27, 2005

Time is only gonna pass you by

I have updates of an app out to TestFlight on version 7.7.0 and am trying to ship a hotfix 7.6.1.

The hotfix went through QA and everything fine via TestFlight, the build is there, but when I try to select it to ship it to the store all I see are 7.7.0 builds. Tried in Chrome and Safari. Sending a new build of the 7.6.1 changes on 7.7.0 would be painful and require annoying regulatory hurdles to be met and documented (healthcare).

Has anyone run into this before?

edit: I am really dumb, the builds are listed in the order they were uploaded not based on their build number. My hotfix was in the middle of my 7.7.0 builds I just kept scrolling past it.

Glimm fucked around with this message at 21:56 on Dec 2, 2020

SaTaMaS
Apr 18, 2003

pokeyman posted:

My guess is the first test loads the model, then the second test tries to load the same model again and you're hooped. Does it go away if you init a single NSManagedObjectModel (like at the module level, so there's only ever one instance) and pass it in to the NSPersistentContainer's initializer? Or you could make it a static var in your test case superclass, just make sure there's only ever one.

I could be barking up the wrong tree, but this is sounding awfully familiar, and that's how I got around it.

edit: yeah this https://stackoverflow.com/questions/51851485/multiple-nsentitydescriptions-claim-nsmanagedobject-subclass

That fixed it, thanks!! I guess XCode can run multiple tests concurrently but I'm still fuzzy on how it happens that when multiple NSPersistentContainers are created in memory the NSManagedObjectModels are all lumped together creating duplicates.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

SaTaMaS posted:

That fixed it, thanks!! I guess XCode can run multiple tests concurrently but I'm still fuzzy on how it happens that when multiple NSPersistentContainers are created in memory the NSManagedObjectModels are all lumped together creating duplicates.

Nice! You can toggle concurrent testing in the scheme editor (go to Test, Info tab, then click Options next to a test bundle and toggle "Execute in parallel"). I think you'll run into it with sequential testing too though, as there's some kind of process-level bookkeeping or caching going on with managed object subclasses and entities.

Fate Accomplice
Nov 30, 2006




ketchup vs catsup posted:

I work on an app with a tableview whose data comes from a realm db.

That tableview’s cells display status information about the model objects - the status info is calculated on the model object, and the cells use a lazy var to access that status info and layout the cell.

This is all done on the main thread, so scrolling performance is bad. I’ve been tasked with moving the calculation of that status info to a background thread.

I’m struggling to figure out how to replace a lazily calculated bool property on the cell that tells model object to do the calculation with something that does that calculation off the main thread without a nested nightmare of functions with completion handlers.

Anyone have any top level insight as to how to do this?

I thought about this some more and my plan is:

in the tableview controller's viewModel:

for each visible cell, dispatch an operation to a background thread to run the calculations, and in the call back set the result as value in a dictionary held by the viewModel and reload the cell if it's visible.

then in cellForRow, look in the dictionary for the key/value and if present, pass that into the cell's configure method.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
Makes sense to me! I'd also make sure not to start a redundant operation if the cell gets scrolled off-screen and back before the initial operation completes.

Fate Accomplice
Nov 30, 2006




pokeyman posted:

Makes sense to me! I'd also make sure not to start a redundant operation if the cell gets scrolled off-screen and back before the initial operation completes.

Is there a clean way to do that? I imagine I’d have to track my dispatches in order to know which to cancel, instead of just firing and forgetting.

Or should I use an operation queue instead?

I managed to go a long way in iOS engineering without doing too much multithreading so I appreciate any advice and things to watch out for like your comment.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

ketchup vs catsup posted:

Is there a clean way to do that? I imagine I’d have to track my dispatches in order to know which to cancel, instead of just firing and forgetting.

Or should I use an operation queue instead?

I managed to go a long way in iOS engineering without doing too much multithreading so I appreciate any advice and things to watch out for like your comment.

Assuming your view models stick around (i.e. you're not recreating them all during scrolling or database changes), I'd just keep track of the calculation state there. Maybe an enum with cases for none, pending, and calculated. Then when the cell is about to appear, you can check the state and fire off the calculation if the state is none. If you want to support cancellation, you could associate a DispatchWorkItem with your enum's pending case.

A dispatch queue makes sense. I'd make a dedicated serial queue for calculations and dispatch to that instead of a global queue.

Oh, and you're probably already doing it, but be careful about which queue you're on when updating the cell and the view model. e.g. when the calculation's done I would dispatch to the main queue to update the view model's state.

fankey
Aug 31, 2001

I have a subproject which builds dylib that my main project is linking to and I can't figure out how to get the code signing to work so I can build and archive. I am able to emulate without any issue.

The error I'm getting is this
code:
Signing for "antlr4" requires a development team. Select a development team in the Signing & Capabilities editor.
The project looks like this






Originally the antlr4 target had a 'Choose Identity' button ( or something similar ). I clicked on that and chose the antlr4_ios.plist and that filled out that section. I've made sure the Team matches my main app and set the every bundle identifier I can find to match with the understanding if I did that I wouldn't need to sign the dylib but I still can't get past that build error.

Edit: Noticed that in the main project that libantlr4-runtime.dylib was set to 'Embed & Sign'. Changing that to 'Embed Without Signing' has no affect and it still looks like it's attempting to sign the dylib for some reason.

fankey fucked around with this message at 19:21 on Dec 3, 2020

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
Can you set the antlr4 target to "don't code sign" in its build settings?

Adbot
ADBOT LOVES YOU

Doc Block
Apr 15, 2003
Fun Shoe
The error message is explicitly saying it can’t be signed because you don’t have a team specified, and in your screenshots you don’t have a team or bundle specified.

Also, shipping it with your app as a framework instead of a dylib is probably gonna be the path of least resistance in the long run.

Doc Block fucked around with this message at 19:42 on Dec 3, 2020

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply