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.

DreadCthulhu posted:

How do you guys handle waiting on multiple async calls? For example, in my app I need to fetch a bunch of data at once from a few separate REST routes. I could do callback chaining, but that'd add an extra 300-400ms to the wait, so I'd rather shoot them all out at once. Prob is that ideally I wouldn't want to manually implement logic to check when all the calls have returned, although it's probably trivial given that the callbacks are all in main queue.

If you're using an NSOperationQueue, make a block operation that depends on the fetches. Otherwise, use a semaphore (or, since everything comes in on a single, serial queue, an integer).

Adbot
ADBOT LOVES YOU

zero knowledge
Apr 27, 2008

DreadCthulhu posted:

How do you guys handle waiting on multiple async calls? For example, in my app I need to fetch a bunch of data at once from a few separate REST routes. I could do callback chaining, but that'd add an extra 300-400ms to the wait, so I'd rather shoot them all out at once. Prob is that ideally I wouldn't want to manually implement logic to check when all the calls have returned, although it's probably trivial given that the callbacks are all in main queue.

Is there anything like a properly working promises framework out there where I could just wait for a collection of promises to complete? How do you guys handle these scenarios?

A dispatch group is ideal in this kind of situation. It sounds like you have an async method that probably looks like:

-[SomeClass doAThingAtURL:(NSURL *)url withCompletion:(dispatch_block_t)completion];

...and you're going to call that multiple times times in parallel. So you could do:

code:
- (void)doABunchOfThingsAndWaitForAllOfThem
{
	dispatch_group_t group = dispatch_group_create();

	dispatch_group_enter(group);
	[instance1 doThingAtURL:url1 withCompletion:^{
		LOG("thing 1 is done");
		dispatch_group_leave(group);
	}];

	dispatch_group_enter(group);
	[instance2 doThingAtURL:url2 withCompletion:^{
		LOG("thing 2 is done");
		dispatch_group_leave(group);
	}];

	dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
}
You'll block in dispatch_group_wait until the group is empty, which won't happen until all the calls to dispatch_group_enter(3) have been balanced by calls to dispatch_group_leave(3). You have to be careful that the completion blocks for each async call aren't on the same queue you're blocking with dispatch_group_wait(3), or you'll deadlock. Fortunately, you can also use dispatch_group_notify(3) to be asynchronously notified on an arbitrary dispatch queue when the group has emptied.

See http://developer.apple.com/library/mac/documentation/Darwin/Reference/ManPages/man3/dispatch_group_wait.3.html for more.

Hughlander
May 11, 2005

DreadCthulhu posted:

How do you guys handle waiting on multiple async calls? For example, in my app I need to fetch a bunch of data at once from a few separate REST routes. I could do callback chaining, but that'd add an extra 300-400ms to the wait, so I'd rather shoot them all out at once. Prob is that ideally I wouldn't want to manually implement logic to check when all the calls have returned, although it's probably trivial given that the callbacks are all in main queue.

Is there anything like a properly working promises framework out there where I could just wait for a collection of promises to complete? How do you guys handle these scenarios?

Dispatch queue as others have mentioned is a great way to solve it, but since you mentioned promises, I've refactored some load logic from sync file operations to async background file with https://github.com/mikeash/MAFuture this routine. It was pretty much just replacing the load call with the future block.

DreadCthulhu
Sep 17, 2008

What the fuck is up, Denny's?!
Thanks for the tips, all those options are great. Dispatch group seems the simplest, even though I'd have to convert the callbacks to be all on a separate thread, which I'm not too sure about how to achieve at this point (it's been a while).

However, I've also noticed that AFNetworking seems to support my scenario out of the box with enqueueBatchOfHTTPRequestOperations, which based on the source looks like would do all of the operations at once, so I'm thinking I'm going to have to rewrite my API client to either enqueue itself right away or to return the operation itself so that it can be batched.

Small White Dragon
Nov 23, 2007

No relation.
I remember hearing back in the day that you could only expand the devices supported in App Updates, and not reduce. However, using a recent Xcode means no mean armv7 and a higher minimum iOS target in an update, I assume that is okay?

The Gripper
Sep 14, 2004
i am winner

Small White Dragon posted:

I remember hearing back in the day that you could only expand the devices supported in App Updates, and not reduce. However, using a recent Xcode means no mean armv7 and a higher minimum iOS target in an update, I assume that is okay?
It shouldn't be a problem, the restriction only comes into play if you're trying to remove compatibility for a device that is supported by the iOS version you're targeting. If you upgrade the required iOS version and that stops older devices from updating (as the iOS version is unsupported) then that is OK.

Echo Video
Jan 17, 2004

UIView block-based animations set up layer animations to actually do the work, so is there a way to grab on to those layer animations after they've been defined in the UIView level?

I'm trying to write custom container view controllers that also support custom transitions, and I want to see if I can do it using the iOS 7 custom transition protocols. In order to make it interactive in the same way as standard view controller transitions, I think I need to be able to control the timing of the animation set by the transition animator delegate. So, any way to grab the animation created by a UIView animation call in order to manipulate it?

Doc Block
Apr 15, 2003
Fun Shoe

Echo Video posted:

UIView block-based animations set up layer animations to actually do the work, so is there a way to grab on to those layer animations after they've been defined in the UIView level?

I'm trying to write custom container view controllers that also support custom transitions, and I want to see if I can do it using the iOS 7 custom transition protocols. In order to make it interactive in the same way as standard view controller transitions, I think I need to be able to control the timing of the animation set by the transition animator delegate. So, any way to grab the animation created by a UIView animation call in order to manipulate it?

You should be able to access them via the view's underlying Core Animation layer. NSArray *animationKeys = [myView.layer animationKeys];.

I don't know if messing with UIKit-created Core Animation animations will mess with anything as far as UIKit is concerned, though.

Echo Video
Jan 17, 2004

Doc Block posted:

You should be able to access them via the view's underlying Core Animation layer. NSArray *animationKeys = [myView.layer animationKeys];.

I don't know if messing with UIKit-created Core Animation animations will mess with anything as far as UIKit is concerned, though.

I figured that for a single layer that I know changed. But I'm thinking/assuming that a UIView animate call ends up creating one CAAnimationGroup that represents all the changes, and that the existing interactive view transitions manipulate that animation. So without knowing the views involved, is there any way to get the animation/animations created from an arbitrary UIView animation method call? Something like

code:
[UIView animateWithDuration:1.0 animations:^(){
	// some animations
}];
CAAnimationGroup = // some code to get the animation group that was presumably just created

E: figured out how to do this, or at least something close: grab the layer for the view where the animation is happening, and adjust the speed and timingOffset to match the progress of whatever interaction the animation is supported to correspond to. More information: CAMediaTiming.

Echo Video fucked around with this message at 01:29 on Aug 13, 2013

lord funk
Feb 16, 2004

Oh man. I just found out that Sprite Kit views are always 100% opaque. I can't drop one into my transparent UIScrollView, which means a whole lot of time spent on a cool UI design I can't use. :(

Doh004
Apr 22, 2007

Mmmmm Donuts...
Any suggestions for a chart/graph library? I just need to plop down some pie charts on the iPhone and iPad, nothing too crazy. Short of just googling, was wondering if anyone had any experience with them? Thanks.

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer
CorePlot is pretty solid.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
I've got an HTMLDocument and some HTMLNode instances. I want to avoid retain cycles, and I'm using ARC. Concretely:
Objective-C code:
@interface HTMLNode : NSObject

@property (strong, nonatomic) HTMLNode *parentNode;
@property (copy, nonatomic) NSArray *childNodes;

@end

@interface HTMLDocument : HTMLNode

@end
and there's a retain cycle between each node and its parent.

So long as anybody has a strong reference to any node in the tree, I want the whole tree (rooted at the document) to stick around. Weak references don't help in either direction. If parentNode is weak, plucking a node out from the middle of a tree can cause everything except the subtree rooted at that node to be deallocated.

I'm not sure what to do. I know this isn't a new problem, but I don't know what to call it and I'm having a hard time reading up on it. What's this called? Is there a way to make it work?

Axiem
Oct 19, 2005

I want to leave my mind blank, but I'm terrified of what will happen if I do
My ten-seconds'-thought solution: have a special function in the node's class called something like clear_from_memory. What it does is it calls this on all of its child nodes (if there are any), then sets all the child nodes to null (eliminating the references to them), then returns up to its parent. Call this on a node and that node and all its descendents will no longer have references to them, so boom, fixed.

The downside is that you still actually have the retain cycles, and you have to call a special function to deallocate.

Thinking about this as a linked list, the way to pull one element out to deallocate is to change its neighbors to point to each other. To eliminate the entire linked list, I'm thinking you still have to one-by-one deallocate the nodes.

Plorkyeran
Mar 22, 2007

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

pokeyman posted:

I'm not sure what to do. I know this isn't a new problem, but I don't know what to call it and I'm having a hard time reading up on it. What's this called? Is there a way to make it work?
There is no good solution. One bad solution is to force someone to manually trigger a deallocation. A less bad, but much more complicated solution is to rather than exposing the cyclic graph directly, expose proxy objects which wrap and retain the cyclic graph, but do not retain each other. When the last of these proxy objects is destroyed, tear down the graph since there's no longer any external references to it.

[e] Something along the lines of the following:
Objective-C code:
@interface BackingNode : NSObject
@property (strong, nonatomic) BackingNode *parent;
@property (strong, nonatomic) NSArray *children;

@property (strong, nonatomic) NSString *thing;
- (void)destroy;
@end

@implementation BackingNode
- (void)destroy {
    [self.parent destroy];
    for (BackingNode *child in self.children)
        [child destroy];
    self.parent = nil;
    self.children = nil;
}
@end

@interface GraphOwner : NSObject
@property (strong, nonatomic) BackingNode *graph;
@end

@implementation GraphOwner
- (void)dealloc {
    [self.graph destroy];
}
@end

@interface Node : NSObject
@property (readonly, nonatomic) Node *parent;
@property (readonly, nonatomic) NSArray *children;

@property (strong, nonatomic) NSString *thing;
@end

@interface Node ()
@property (strong, nonatomic) GraphOwner *graphOwner;
@property (strong, nonatomic) BackingNode *node;
@end

@implementation Node
- (instancetype)initWithBackingNode:(BackingNode *)node graphOwner:(GraphOwner *)graphOwner {
    if (!(self = [super init])) return self;
    self.node = node;
    self.graphOwner = graphOwner;
    return self;
}

- (Node *)parent {
    return [[Node alloc] initWithBackingNode:self.node.parent graphOwner:self.graphOwner];
}

- (NSArray *)children {
    // a loop and stuff
}

- (NSString *)thing {
    return self.node.thing;
}
@end
There are a bunch of obvious drawbacks to this approach.

Plorkyeran fucked around with this message at 03:25 on Aug 14, 2013

Doctor w-rw-rw-
Jun 24, 2008

pokeyman posted:

So long as anybody has a strong reference to any node in the tree, I want the whole tree (rooted at the document) to stick around. Weak references don't help in either direction. If parentNode is weak, plucking a node out from the middle of a tree can cause everything except the subtree rooted at that node to be deallocated.

I'm not sure what to do. I know this isn't a new problem, but I don't know what to call it and I'm having a hard time reading up on it. What's this called? Is there a way to make it work?

Hmm. Use weak references. Then have a manager class that has a strong reference to everything for that document and manages adding to and removing from the collection. The manager owns the collection and when it gets deallocated it takes the collection with it.

Would that work?

Edit: after thinking about it somewhat I might be misunderstanding. But it sounds like something needs responsibility for the whole graph. If nodes depend on their parents, that has to be a strong property, and you need to decide when to destroy the graph. That needs to be decided by something; you can't just traverse a graph and decide to remove it when nothing references it. That's literally garbage collection, and you need a collector for that.

Doctor w-rw-rw- fucked around with this message at 03:49 on Aug 14, 2013

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Doctor w-rw-rw- posted:

Hmm. Use weak references. Then have a manager class that has a strong reference to everything for that document and manages adding to and removing from the collection. The manager owns the collection and when it gets deallocated it takes the collection with it.

Would that work?

Edit: after thinking about it somewhat I might be misunderstanding. But it sounds like something needs responsibility for the whole graph. If nodes depend on their parents, that has to be a strong property, and you need to decide when to destroy the graph. That needs to be decided by something; you can't just traverse a graph and decide to remove it when nothing references it. That's literally garbage collection, and you need a collector for that.

Yeah it occurred to me that anything I implement is at best an ad hoc refcounting scheme.

I think, for now at least, I'll just make the parentNode property weak, and if you want to keep the tree around then keep a reference to the document (or root of the tree).

Meat Street
Oct 17, 2004

knowin' nothin' in life but to be legit
I might be braindead from staring at this code too long tonight, but I'll ask just in case: did UITextView/keyboard interaction change drastically in iOS 7?

I have a textview and an imageview stacked on top of each other in a parent scroll view, and I can't for the life of me get the scroll view to follow the input cursor while editing text. Everything I've found online suggests that this was gratis in iOS 6, but I'm getting nowhere fast. Anyone have experience here?

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer

Plorkyeran posted:

There is no good solution. One bad solution is to force someone to manually trigger a deallocation. A less bad, but much more complicated solution is to rather than exposing the cyclic graph directly, expose proxy objects which wrap and retain the cyclic graph, but do not retain each other. When the last of these proxy objects is destroyed, tear down the graph since there's no longer any external references to it.


There are a bunch of obvious drawbacks to this approach.

This is kinda what I was thinking. If you had all the HTTP node methods return proxy objects that had a strong reference to the root document, you'd kinda be able to hack around the problem. You'd make the *parentNode properties weak, and the HTMLDocument would be held onto by the proxy. When all the proxies dealloc, then all the references to the root HTMLDocument will have dealloed, and the tree will deconstruct itself.

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



pokeyman posted:

Yeah it occurred to me that anything I implement is at best an ad hoc refcounting scheme.

I think, for now at least, I'll just make the parentNode property weak, and if you want to keep the tree around then keep a reference to the document (or root of the tree).

How were you going to access the tree if you didn't keep a reference to it before?

E: Doy, via the weak parentNode of course. Nevermind :downs:

Carthag Tuek fucked around with this message at 08:20 on Aug 14, 2013

Lumpy
Apr 26, 2002

La! La! La! Laaaa!



College Slice
Autolayout question:

I have a table with static cells. In my sotryboard, I dragged a button out to the left side, aligned it via the guides so it "snapped". Dragged another button over to the right side in the same fashion. Dragged a label in and "snapped" it the standard distance to the button on the left side. I want to drag it wider so the right edge snaps the "standard" distance from the button on the right, but I cannot drag to resize the label in any way. If I add text to the label, it's truncated, as the label seems fixed at the width of the 'Label' default text.

This is in the newest release of Xcode 5. Did something change in auto-layout land, as I seem to have done this before.

DreadCthulhu
Sep 17, 2008

What the fuck is up, Denny's?!
Sorry for bringing this up again, I asked about this a while ago, and I'm wondering if the situation changed in the past year or so. What do people use here for dynamically downloading large sets of pictures into the app's folder tree? You guys recommended libgit2 at some point, and I'm looking into that right now, but I'm wondering if I could go simpler.

Basically I want to ship the app in under 3-5 megs and I have over 100 megs of images I might need to download at some point (the connection of our users will be pretty wimpy so I'd like to just download things once and not expect continuous caching to work predictably).

I'd also like to be able to update these cached image versions when they are indeed changed, and this is where git was going to come in very handy, as opposed to a hand-written solution. Ideally the app would start, and I would put up a waiting screen with a progress bar for 20-30 secs while the basic set of images is downloaded (it's a b2b product so they can wait), and then the user can go ahead and not worry about it any longer.

DreadCthulhu fucked around with this message at 22:10 on Aug 14, 2013

Doctor w-rw-rw-
Jun 24, 2008

DreadCthulhu posted:

Sorry for bringing this up again, I asked about this a while ago, and I'm wondering if the situation changed in the past year or so. What do people use here for dynamically downloading large sets of pictures into the app's folder tree? You guys recommended libgit2 at some point, and I'm looking into that right now, but I'm wondering if I could go simpler.

Basically I want to ship the app in under 3-5 megs and I have over 100 megs of images I might need to download at some point (the connection of our users will be pretty wimpy so I'd like to just download things once and not expect continuous caching to work predictably).

I'd also like to be able to update these cached image versions when they are indeed changed, and this is where git was going to come in very handy, as opposed to a hand-written solution. Ideally the app would start, and I would put up a waiting screen with a progress bar for 20-30 secs while the basic set of images is downloaded (it's a b2b product so they can wait), and then the user can go ahead and not worry about it any longer.

I didn't recommend it, I suggested it as a crazy data-versioning/deduplication/syncing technique. The simplest solution is probably to just have a text file or sqlite db or json file you download that maps image filenames and/or hashes <-> last updated date, then check that against a local text file/sqlite db/json file and re-download the different ones.

For good measure, if your CDN or file storage supports etags, see if you can make it so the clients only ever update to the latest file database if the etag is different.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

DreadCthulhu posted:

Basically I want to ship the app in under 3-5 megs and I have over 100 megs of images I might need to download at some point (the connection of our users will be pretty wimpy so I'd like to just download things once and not expect continuous caching to work predictably).

I'd also like to be able to update these cached image versions when they are indeed changed

HTTP. Use Etag, Last-Modified, or your favourite HTTP header. It's so much easier than a git client.

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



Hey pokeyman

Is there anything I gotta be careful about when checkin in an xcode project thats going live on ios? like profiles or whatever. whatta i gotta put in my .gitignore

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Carthag posted:

Is there anything I gotta be careful about when checkin in an xcode project thats going live on ios? like profiles or whatever. whatta i gotta put in my .gitignore

My gitignore for Xcode projects is pretty short these days:

code:
xcuserdata
*.xccheckout
I also make sure to leave the automatic setting for "Code Signing Identity", otherwise people clone the repo and it won't build. But that's it I think.

Doc Block
Apr 15, 2003
Fun Shoe
I've also got
code:
*.DS_Store
*.swp
*~.nib
and usually a bunch of lines excluding stuff from the Xcode 3 days because I just copy the same .gitignore from old projects over to my new ones.

Doctor w-rw-rw-
Jun 24, 2008
Definitive answer: https://gist.github.com/adamgit/3786883

Remove as necessary for things you care about which might only ever be one thing there, ever, if that.

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



Thanks guys =)

Plorkyeran
Mar 22, 2007

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

Doc Block posted:

I've also got
code:
*.DS_Store
*.swp
*~.nib
and usually a bunch of lines excluding stuff from the Xcode 3 days because I just copy the same .gitignore from old projects over to my new ones.

Things like .DS_Store and .swp should be in your global .gitignore rather than per-repository ones.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Plorkyeran posted:

Things like .DS_Store and .swp should be in your global .gitignore rather than per-repository ones.

So should the Xcode poo poo. Problem is you can't count on anyone else having a sensible global gitignore!

DreadCthulhu
Sep 17, 2008

What the fuck is up, Denny's?!

Doctor w-rw-rw- posted:

I didn't recommend it, I suggested it as a crazy data-versioning/deduplication/syncing technique. The simplest solution is probably to just have a text file or sqlite db or json file you download that maps image filenames and/or hashes <-> last updated date, then check that against a local text file/sqlite db/json file and re-download the different ones.

For good measure, if your CDN or file storage supports etags, see if you can make it so the clients only ever update to the latest file database if the etag is different.

Yeah I think I'm going to go with the former. I gave libgit2 a shot but I was getting all sorts of issues, anywhere from bugs to having a version of the library without SSL support etc etc. Automatically generating a JSON index based of git log history and uploading it together with all my images to S3 ended up being way simpler.

HiriseSoftware
Dec 3, 2004

Two tips for the wise:
1. Buy an AK-97 assault rifle.
2. If there's someone hanging around your neighborhood you don't know, shoot him.
Concerning iOS In-App Purchases, what's the best practices for dealing with receipt validation that fails because of some sort of network error, etc (i.e. if something was wrong on server side)? Should I not call finishTransaction: on the payment queue so that completeTransaction (and my verification) runs again? Should I store the receipt later and try to verify it again at some point in the future? At this point content hasn't been delivered, since I only want to do that unless I verify the receipt successfully.

On this page http://zoooot.com/732/my-experiences-with-verifying-in-app-purchase-receipts the author doesn't store failed receipts and just says to the user "Try your purchase again later, you won't be charged again" but that doesn't make sense to me for something like consumables. I left comments on his post asking for clarification, but I wanted to know what you guys think?

Doh004
Apr 22, 2007

Mmmmm Donuts...
Does it take a while for the developer preview to get updated on the site? I still only see 5 even though 6 was released?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
iOS 7 beta 6 appears to have just a single change which is unrelated to developer stuff, so I'm guessing there's no new Xcode version to go with it.

Doh004
Apr 22, 2007

Mmmmm Donuts...

Plorkyeran posted:

iOS 7 beta 6 appears to have just a single change which is unrelated to developer stuff, so I'm guessing there's no new Xcode version to go with it.

Text on the site:

Xcode 5 and iOS 7 SDK beta 5
What's New in Xcode
Xcode 5 Developer Preview 5 Release Notes

:\

And when you try to download the dmg, it still says 5 in the filename.

Doh004 fucked around with this message at 17:26 on Aug 16, 2013

carry on then
Jul 10, 2010

by VideoGames

(and can't post for 10 years!)

Yeah, I don't think anything related to the SDK was changed. I got an email from Apple that mentioned it fixed a bug with iTunes, so there's probably no need for an Xcode beta 6.

lord funk
Feb 16, 2004

I've forgotten how to get symbols back up in Instruments. Since updating to beta 5 I've been getting this:

HiriseSoftware
Dec 3, 2004

Two tips for the wise:
1. Buy an AK-97 assault rifle.
2. If there's someone hanging around your neighborhood you don't know, shoot him.

lord funk posted:

I've forgotten how to get symbols back up in Instruments. Since updating to beta 5 I've been getting this:


I just used this the other day:

http://stackoverflow.com/questions/5268041/xcode-4-instruments-doesnt-show-source-lines

Not sure if it'll work in Xcode 5, but hopefully it'll help.

Adbot
ADBOT LOVES YOU

lord funk
Feb 16, 2004

HiriseSoftware posted:

I just used this the other day:

http://stackoverflow.com/questions/5268041/xcode-4-instruments-doesnt-show-source-lines

Not sure if it'll work in Xcode 5, but hopefully it'll help.

Aww, my app is the only one with a DSYM. I can see my methods, but not anything else. It's making it really hard to figure out what UIKit / Quartz stuff is dragging my app to a halt.

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