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
Doc Block
Apr 15, 2003
Fun Shoe
To throw my two cents into this (because of course people care what I think, right? ;) ):

Laying out a UI is much easier for me if I can actually see what I'm doing vs typing in position values, even for UIs that I've already drawn out on paper or in Photoshop. All the manual UI layout in code that I've ever done was hard to keep from turning into an ugly, fragile mess. Never mind the tedium of actually creating UI elements in code, what with the line after line after line of just setting properties, then trying to figure out why it doesn't behave like it does when created in Interface Builder.

So Interface Builder because it lets me see what I'm doing , and autolayout because it lets me have dynamic layouts without having to resort to messy UI layout code.

Plus, on OS X you get Cocoa Bindings, which is great for eliminating UI glue code. Just hook your preference checkboxes to NSUserDefaults and call it a day.

Also, I try not to be the kind of programmer that insists on fighting the tools and doing everything the hard way.

https://www.youtube.com/watch?v=QhhFQ-3w5tE&t=1496s

Doc Block fucked around with this message at 00:34 on Jun 12, 2016

Adbot
ADBOT LOVES YOU

Doctor w-rw-rw-
Jun 24, 2008
I start from a different spot. When I am forced to use Autolayout (which I haven't been in a while), I audit the IB xml exhaustively because it randomly changes poo poo at the drop of a hat. If I have repetitive UI elements, I have to sync any tweaks on one of them to all of them. If I have to tie a button to a function, I make sure its targets are correct, and that the declarations are in the right place. I also check constraints constantly against multiple sizes, and ensure they're anchored to the right thing. There is no universe in which I am both certain the IB + Autolayout code is correct and where the act of verifying that this is so was less labor-intensive than just writing the code. Also, echoing the stringly typed complaint.

The visual element is solved by running it in the simulator, and piping the data in to the views cleanly enough that mocking it is trivial.

Also, I'm just as allergic to messy UI layout code, which is why I never write messy UI layout code.

Doc Block posted:

Plus, on OS X you get Cocoa Bindings, which is great for eliminating UI glue code. Just hook your preference checkboxes to NSUserDefaults and call it a day.
Magic that changes reality out from under you: sounds wonderful (for bugs).

Doc Block posted:

Also, I try not to be the kind of programmer that insists on fighting the tools and doing everything the hard way.
Using IB and Autolayout requires one to be prepared for war with them at any time.

Data Graham
Dec 28, 2009

📈📊🍪😋



One issue I have with IB is that working visually with a complex layout gets sloooooooooooow.

I'm on a 2012 MBP, and right now I'm cruising through this view controller functionality-wise; but I'm spending 2/3 of my layout time with my cursor pinwheeling while I wait to update constraints or align an element. I'd better get it right the first time or I'm gonna be up all night.

Watching that video, I'm envious of 1997-era NeXT boxes and how snappy they were

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
I love when IB says everything is fine for layout yet NSIBPrototypingLayoutConstraint still gets inserted :argh:

Doc Block
Apr 15, 2003
Fun Shoe

Doctor w-rw-rw- posted:

I start from a different spot. When I am forced to use Autolayout (which I haven't been in a while), I audit the IB xml exhaustively because it randomly changes poo poo at the drop of a hat. If I have repetitive UI elements, I have to sync any tweaks on one of them to all of them. If I have to tie a button to a function, I make sure its targets are correct, and that the declarations are in the right place. I also check constraints constantly against multiple sizes, and ensure they're anchored to the right thing. There is no universe in which I am both certain the IB + Autolayout code is correct and where the act of verifying that this is so was less labor-intensive than just writing the code. Also, echoing the stringly typed complaint.

I cannot imagine an alternate universe where I would ever want to open up a .xib and inspect the contents even once, let alone after every change.

quote:

The visual element is solved by running it in the simulator, and piping the data in to the views cleanly enough that mocking it is trivial.

How do you make tweaks this way? How do you give elements their initial placement? Lots of tedious iteration. Or I could just plop the element down in IB, set up the constraints, and move on.

quote:

Magic that changes reality out from under you: sounds wonderful (for bugs).

The parts of your app that care about user preferences should be listening for preference change notifications, so it doesn't matter. All your UI glue code would be doing is piping the preferences from the UI to NSUserDefaults anyway.

And Cocoa Bindings works the other way, too. Changes made to whatever you've got your UI connected to through Cocoa Bindings will be immediately reflected in the UI, without having to write any KVO stuff yourself.

quote:

Using IB and Autolayout requires one to be prepared for war with them at any time.

I don't share your contempt.

Doc Block fucked around with this message at 02:11 on Jun 12, 2016

Toady
Jan 12, 2009

I've been sympathetic to complaints about IB over the years, but I can't imagine recreating the functionality of autolayout, size classes, bindings, and other automatic features in code. Many of these tools are the recommended solution; e.g., the documentation tells you to "support right-to-left languages by using base internationalization and Auto Layout."

Doc Block
Apr 15, 2003
Fun Shoe
IB and autolayout certainly aren't perfect, to be sure.

Doctor w-rw-rw-
Jun 24, 2008

Doc Block posted:

I cannot imagine an alternate universe where I would ever want to open up a .xib and inspect the contents even once, let alone after every change.
I control everything that goes into a (non-checkpoint) commit. I regularly select and stage/discard changes to my commits, and I control for merge conflicts. The thing about committing a visually-edited serialized object is that the editor won't be intelligent about the change, and may package up irrelevant or even incorrect changes alongside the good ones. I've even taken to closing out IB, editing the .xib files by hand in a text editor, then reopening it in IB when IB would just not stop loving it up.

Doc Block posted:

How do you make tweaks this way? How do you initially place elements? Guesswork and lots of iteration, in my experience. Or I could just plop the element down in IB, set up the constraints, and move on.
Const-ized values for things that might change size.

Doc Block posted:

The parts of your app that care about user preferences should be listening for preference change notifications. OS X users expect changes made in preference panels to happen immediately, anyway.

And Cocoa Bindings works the other way, too. Changes made to whatever you've got your UI connected to through Cocoa Bindings will be immediately reflected in the UI, without having to write any KVO stuff yourself.
Major preference changes which, if respected immediately, would trigger catastrophic performance, cause mixed presentation of old/new views or experiences based on when they were created, or require cache invalidation means deciding the lifecycle of a configuration change carefully. I would prefer to handle the live updating explicitly. I'm not a big fan of notifications –a stringly typed event bus with human-named events for applications is pretty weakly typed/weakly linked for my tastes and thus prone to nasty surprises.

Doc Block posted:

I don't share your contempt.
Doing battle with the tools isn't an insult, it's a fact: Debugging is a bigger chore, and they also make it hard to be confident that something is correct (as much as possible), understandable, and performant all at the same time. Doubly so when its internal resolution mechanisms are for the most part a black box.

stuffed crust punk
Oct 8, 2004

by LITERALLY AN ADMIN
Please tell me I'm not insane and "stringly-typed" has been an autocorrect thing

Doctor w-rw-rw-
Jun 24, 2008

Regular Nintendo posted:

Please tell me I'm not insane and "stringly-typed" has been an autocorrect thing

You're insane? http://c2.com/cgi/wiki?StringlyTyped

Programming jargon.

Data Graham
Dec 28, 2009

📈📊🍪😋



I love that their canonical example of that is ColdFusion.

Guess what I have to use for my backend API

Doc Block
Apr 15, 2003
Fun Shoe

Doctor w-rw-rw- posted:

Const-ized values for things that might change size.

That's not really what I mean. I have a hard time even knowing what values to use in the first place if I haven't already seen it. Should this be 10 points? 20? 100? Who knows?

quote:

Major preference changes which, if respected immediately, would trigger catastrophic performance, cause mixed presentation of old/new views or experiences based on when they were created, or require cache invalidation means deciding the lifecycle of a configuration change carefully. I would prefer to handle the live updating explicitly. I'm not a big fan of notifications –a stringly typed event bus with human-named events for applications is pretty weakly typed/weakly linked for my tastes and thus prone to nasty surprises.

So how would you handle preference changes? At some point you're stuffing the preference in NSUserDefaults (or wherever) and then you need a way to let anything that cares know the preference was changed (and since NSUserDefaults automatically fires off a notification if something changes...). On OS X the user's expectation is that preference changes happen immediately; no hitting an "OK" button or restarting the app for the change to take effect. So even if you did it all in code, with no Cocoa Bindings, the user would expect the change to happen the instant they ticked the checkbox or whatever.

Having otherwise unrelated parts of an application be able to fire off one-way, one-to-many messages while still remaining decoupled is pretty handy IMHO.

quote:

Doing battle with the tools isn't an insult, it's a fact: Debugging is a bigger chore, and they also make it hard to be confident that something is correct (as much as possible), understandable, and performant all at the same time. Doubly so when its internal resolution mechanisms are for the most part a black box.

Fighting the tools can also just be a sign of a stubborn programmer ;)

Gul Banana
Nov 28, 2003

if i felt compelled to ensure that xib changes looked clean in source history i would certainly not want to use autolayout, but i would also consider therapy

Doctor w-rw-rw-
Jun 24, 2008

Gul Banana posted:

if i felt compelled to ensure that xib changes looked clean in source history i would certainly not want to use autolayout, but i would also consider therapy
You know, it's throwaway comments like this that makes talking about mental health issues feel shameful when they really ought not to be.

Thanks for that, by the way. Really made me feel good about /actually/ seeking therapy. /s

In any case, I encountered Xcode lying about undoing things, deleting or changing object IDs, and otherwise getting into strange states enough times to be very wary of the contents of the xib changes. If I'm going to be forced to use a system whose inner workings are largely out of my control, I'm going to at least control what I can so the inevitable bugs are easier for me to find and understand (and bisect, if it's particularly nasty).

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Doctor w-rw-rw- posted:

In any case, I encountered Xcode lying about undoing things, deleting or changing object IDs, and otherwise getting into strange states enough times to be very wary of the contents of the xib changes. If I'm going to be forced to use a system whose inner workings are largely out of my control, I'm going to at least control what I can so the inevitable bugs are easier for me to find and understand (and bisect, if it's particularly nasty).

I do this too, and it gets real tiring. It saves me from some Xcode stupidity maybe a couple times a year. I can never decide if it's worthwhile.

Also I'll admit to hand-editing a storyboard now and then to reparent a subtree without losing all the constraints. Can't figure out how to do that in IB.

Doh004
Apr 22, 2007

Mmmmm Donuts...
Holy IB/Autolayout chat. All valid points for sure.

I'd say my biggest grip with laying things out in Nibs/Storyboard is that I find it hard for apply UI changes universally. When UIAppearance isn't specific enough, having to change the textColor or the font for a lot of elements takes a long time because I can't just refactor or find/replace all from within IB easily which sucks. It involved a lot more manual changes on my part than I wanted, specifically in the color palette.

lord funk
Feb 16, 2004

It's also worth remembering that we're all doing different kinds of views. I've got a few views that 100% couldn't be done with IB / autolayout, but I'm sure a login form sheet with a few textfields and labels is okay.

brap
Aug 23, 2004

Grimey Drawer
I think that Interface Builder would be improved substantially by orienting it around human-readable markup, like the WPF designer (not that XAML is that awesome to work with) that splits the UI half and half between the visual designer and markup. Anything less seems like a disrespect to developers, who are inevitably going to need to merge those documents.

It also seems like UIStackView as opposed to constraints is an admission of "okay, how can we provide a layout tool that does what developers actually need?" I'm expecting that new UIs that people build (if they can get away with targeting iOS 9, and that time seems almost upon us) will be making heavy use of them and minimal use of constraints except to say "yeah, make this table view the size of the whole view controller" and stuff like that. Obviously you can do more powerful things with constraints that you can't do with UIStackView and so on, but it goes a long way toward simplifying typical use cases.

Doc Block
Apr 15, 2003
Fun Shoe

fleshweasel posted:

I think that Interface Builder would be improved substantially by orienting it around human-readable markup, like the WPF designer (not that XAML is that awesome to work with) that splits the UI half and half between the visual designer and markup. Anything less seems like a disrespect to developers, who are inevitably going to need to merge those documents.

Would it still just be serialized objects, though?

And editing a text file to create your UI is only a very, very small step above creating it in code IMHO.

brap
Aug 23, 2004

Grimey Drawer
It would be some XML variant, yeah, and you'd be able to drag and drop and nudge and set properties and whatever you want in the visual designer and see all your changes reflected in the markup while you're doing it. Similarly, when making changes in the markup you'd see the visual designer update regularly. IDEs with autocomplete based on the document's schema can go a huge way toward making all this stuff productive even if it sounds lovely.

I also have the feeling that storyboards, while convenient, are really prone to bloat and they get really goddamn slow when they bloat.

Doc Block
Apr 15, 2003
Fun Shoe
Yeah, one thing about IB I avoid is storyboards.

They don't even lessen the amount of code you have to write, since you still have to write prepareForSegue or whatever method to set properties on the next view controller.

Dessert Rose
May 17, 2004

awoken in control of a lucid deep dream...
I really need to get out of storyboard land for my app, it seemed like such a good idea when I started and now it's just ... nope.

Speaking of which. I've been punting on this for a while because it sounds like such an ugly problem to solve, but here I am at the point where I've written all the placeholder code for this app and now I'm designing/implementing actual features, so this big feature I've been punting because it seems hard is ... well, actually hard.

I'm using Core Data, and I want to implement a rules engine in it.

Specifically, I want to generate "reminders" based on the state of the world: if I enter a predefined region, my app wakes up and reads out all of its rules, then schedules a bunch of local notifications based on them. So if "this item has not been completed yet today", and I'm at "work", then schedule a notification for an hour from now (or the time I first showed up at work today, or whatever). This naturally decomposes into Conditions and Actions, which have various fields containing constants and pointing at objects.

Where I'm stuck is designing a schema for this that won't turn into a giant mess. I've seen similar systems implemented by just having five or so fields of a few useful data types and a type field which determines what those are even used for. That seems like the path of least resistance here; Core Data is totally fine adding new optional fields to a schema without having to write a migration. So that's one way to go.

But is that my best option? Other options that I've considered:
- Instead of generic fields, every time a new rule comes along, add all of its fields to the object, and leave everything else null
- Instead of monolithic "Condition" and "Action" entities, make a new entity type for every single new rule type, then depend on inheritance elsewhere to make sense of the hierarchy
- comedy "just serialize JSON into the DB" option

Neither of those seem really any better than the monolithic entity approach, which has the advantage that implementing new rules may not need any DB schema modification whatsoever.

Any other ideas? Has anyone designed anything like this before and done something that turned out well, or poorly?

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

fleshweasel posted:

I also have the feeling that storyboards, while convenient, are really prone to bloat and they get really goddamn slow when they bloat.

Storyboard References help a ton here.

Toady
Jan 12, 2009

I've had few problems with storyboards since they introduced storyboard references. My UIs are kept in separate storyboards just like they were with regular nibs.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed

Dessert Rose posted:

Has anyone designed anything like this before and done something that turned out well

Not really, no.

So, the first thing to understand is that by writing a Rules Engine, you're actually writing an interpreter for a lovely overly-specific programming language. You should probably think about if you actually need this, or if you can get away with building JS strings that you call eval on, so that you only need to write the editor interface and JS bindings (which is super-duper easy with JSC) rather than an interpreter for a language that will almost certainly scope-creep into more and more features.

The next thing to understand is that you're proposing storing the AST in a relational database. As you've noticed it's somewhat of an awkward fit, so the obvious question is to ask what you're gaining from it. Will you actually have a lot of rules? If you're only going to have like ten then you probably could just dump them all to a plist and don't bother with a database at all. If you do need to support having enough rules that deserializing them all on startup and serializing them all after every change is unreasonable, the next question is if you actually need to be able to perform nontrivial queries on them (search for all Rules with an Action of a certain type? All Rules involving "when I get home"?). If not, the json dump in the DB might not be a terrible idea.

If you actually do need to store the AST as proper DB objects, my advice would be to actually embrace the fact that you're storing an AST and design a schema for that, as opposed to trying to encode the semantic meaning of your specific conditions and actions in the schema.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
I didn't even think of JavaScriptCore, thats a great idea. Maybe.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
It's either a great idea or a completely terrible idea, and it's usually hard to tell which in advance.

Doctor w-rw-rw-
Jun 24, 2008

Plorkyeran posted:

It's either a great idea or a completely terrible idea, and it's usually hard to tell which in advance.

Despite being someone who generally hates JS, evalling JS to evaluate rules – as long as it's within a restricted environment – sounds like a pretty good idea to me.

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?

fleshweasel posted:

I have a pretty small (few thousand lines of code) iOS project primarily in Swift that I'm looking at porting to OS X. What kind of solution should I be looking at for this? Single project with some source files building on multiple targets? Multiple projects? Dynamic frameworks?

Single project with multiple targets, splitting your core logic that's the same on all platforms into a separate framework (with its own tests, of course).

You can use the SUPPORTED_PLATFORMS build setting to create a single framework target that builds for multiple platforms; the identifiers it takes are the same type that are used for platform SDKs, e.g. set it to macosx iphoneos iphonesimulator to have a framework target that can be built for all three.

This doesn't mean a single framework bundle will work on multiple platforms, of course. A single Mach-O should only ever contain code for a single platform, no matter what shenanigans people on the Internet will try to pull with lipo. But being able to build the same code for multiple platforms will make developing and testing a framework like that much easier.

stuffed crust punk
Oct 8, 2004

by LITERALLY AN ADMIN
It might just be my personal preference/experience but gently caress Storyboards Forever

Gul Banana
Nov 28, 2003

Doctor w-rw-rw- posted:

You know, it's throwaway comments like this that makes talking about mental health issues feel shameful when they really ought not to be.

Thanks for that, by the way. Really made me feel good about /actually/ seeking therapy. /s

IMO it wouldn't be shameful to have some kind of OCD or equivalent- as programmers we tend to be odd people, & I've seen a psychiatrist myself.
however, it wasn't worth creating that impression for the sake of a joke. sorry

Doctor w-rw-rw-
Jun 24, 2008
Thanks, and I also recognize your point (that the approaches I take fall outside normal parameters) is true in some respects.

Data Graham
Dec 28, 2009

📈📊🍪😋



Having an issue with thread safety and table view cell sizing.

I'm pulling table data from a web service, and I want to show each table cell as a couple of custom text views (think subject and HTML-formatted message; basically a News page). I'm calculating the height of the cells like this:

code:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSDictionary *d = (NSDictionary *)[self.newsArray objectAtIndex:indexPath.row];
    CGFloat thenewsHeight = [self dynamicHeightForHTMLAttributedString:[d valueForKey:@"thenews"] UsingWidth:320 AndFont:[UIFont systemFontOfSize:14.0f]];
    return thenewsHeight + 50;
}

-(CGFloat)dynamicHeightForHTMLAttributedString:(NSString *)dataString UsingWidth:(CGFloat)width AndFont:(UIFont *)font
{
    NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObject:font
                                                                forKey:NSFontAttributeName];
    
    NSMutableAttributedString *htmlString =
    [[NSMutableAttributedString alloc] initWithData:[dataString dataUsingEncoding:NSUTF8StringEncoding]
                                            options:@{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType,
                                                      NSCharacterEncodingDocumentAttribute:[NSNumber numberWithInt:NSUTF8StringEncoding]}
                                 documentAttributes:NULL error:nil];
    
    [htmlString addAttributes:attrsDictionary range:NSMakeRange(0, htmlString.length)];
 
    NSInteger MAX_HEIGHT = 2000;
    UITextView * textView = [[UITextView alloc] initWithFrame: CGRectMake(0, 0, 320, MAX_HEIGHT)];
    textView.attributedText = htmlString;
    [textView sizeToFit];
    return textView.frame.size.height;

}
Which works, but only once. If I try to refresh the view, it crashes on the [textView sizeToFit] line:

code:
2016-06-13 06:59:01.359 foo[30687:2965758] *** Assertion failure in void _UIPerformResizeOfTextViewForTextContainer(NSLayoutManager *, UIView<NSTextContainerView> *, NSTextContainer *, NSUInteger)(), /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIFoundation_Sim/UIFoundation-432.1/UIFoundation/TextSystem/NSLayoutManager_Private.m:1551
2016-06-13 06:59:01.364 foo[30687:2965758] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!'
So I know I need to run some part of this routine on the main thread, but I'm not sure how to go about that, since I have to return a height value; I can't return from inside a dispatch block.

Something obvious I'm missing here?

Thanks—

Doctor w-rw-rw-
Jun 24, 2008

Data Graham posted:

Something obvious I'm missing here?
As a rule, you should never be doing any allocation, initialization, or usage of a view object anywhere but on the main thread. If you're calling dynamicHeightForHTMLAttributedString:(...) from anywhere but the main thread, that's your issue; you're likely to crash on the view stuff.

Also, you're creating, sizing, and throwing away an entire UIView to get text height. Words can't begin to describe how incredibly wasteful and slow that is.

Try -[NSAttributedString boundingRectWithSize:options:context:] for that.

Or use ComponentKit and avoid the UITableView dynamic-sizing shitshow altogether :getin:

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Doctor w-rw-rw- posted:

Also, you're creating, sizing, and throwing away an entire UIView to get text height. Words can't begin to describe how incredibly wasteful and slow that is.

Try -[NSAttributedString boundingRectWithSize:options:context:] for that.

Or don't throw the view away when you're done.

Doc Block
Apr 15, 2003
Fun Shoe
Sounds like you hit an iOS bug. The -tableView:heightForRowAtIndexPath: method should only be getting called on the main queue, and since I don't see any queue/thread stuff in either of your methods it sounds like a bug in -sizeToFit.

There are ways to determine the size of text than by creating a UILabel and then checking it's frame after sizeToFit, BTW.

Either NSString or NSAttributedString have methods for doing this explicitly. I'm posting from my phone or I'd look them up.

Data Graham
Dec 28, 2009

📈📊🍪😋



Yeah, I figured there must be. I'll try the one-line approach as soon as I'm in.

I was sure there's a more straightforward way to do this since I'm basically trying to accomplish exactly what the Awful app does, and it's stable as hell. Also it always sizes the bounding box correctly, whereas my next challenge will be figuring out why my approach always seems to miscalculate and overestimate the height by some arbitrary amount.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
Awful uses self-sizing table view cells. They work like 98% of the time, though maybe I'm doing something wrong. Many times I've thought about switching away from self-sizing cells.

Data Graham
Dec 28, 2009

📈📊🍪😋



Oh ho

I did not know that was a thing.

(My experience with iApp programming in a nutshell)

Adbot
ADBOT LOVES YOU

Doctor w-rw-rw-
Jun 24, 2008

pokeyman posted:

Awful uses self-sizing table view cells. They work like 98% of the time, though maybe I'm doing something wrong. Many times I've thought about switching away from self-sizing cells.

Uh...you mean you AREN'T working on the buggy bookmarks cell sizing that has reproduced virtually on demand for the past year?

EDIT: yep literally just opened the app and behold the buggy cell sizing not responding to text size

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