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.

Axiem posted:

It just seemed odd to me that it used to be that you had to declare explicitly that a variable was readwrite privately, but now you don't have to, and no one seems to have been notified of the change, and I can't find any reference to it online (though it's hard to google for).

Why do keywords like readwrite, atomic, and strong exist if they're the default and therefore never should be used?

I wouldn't say they shouldn't be used. strong especially doesn't belong in that list, as assign is the default for non-object types. The other two you don't tend to see except when people like to be explicit, as mentioned.

I think it was a compiler bug that required specifying readwrite for a little while, and if so then announcing its being fixed was probably pretty quiet. Maybe you'll find it if you comb through LLVM commit messages (enjoy!), or you might get lucky on openradar.

Adbot
ADBOT LOVES YOU

HookShot
Dec 26, 2005
I finally ran into problems with XCode 4, and need to upgrade to 5. I'm running a mac that still has OSX Leopard, there's no way I can upgrade to Lion and install XCode 5, is there? I just need to buy a laptop that wasn't considered new in like 2008, correct?

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Some 2008 machines can run 10.9, and if yours can't then 10.7 is an option. Upgrading from 10.5 is a bit tricky due to it being pre-app store, but apparently you can just contact apple support to get installation media for 10.6 these days (and then upgrade to 10.7 normally).

HookShot
Dec 26, 2005

Plorkyeran posted:

Some 2008 machines can run 10.9, and if yours can't then 10.7 is an option. Upgrading from 10.5 is a bit tricky due to it being pre-app store, but apparently you can just contact apple support to get installation media for 10.6 these days (and then upgrade to 10.7 normally).

Oh ok awesome, I thought 10.8 was the oldest possible version for XCode 5, I don't think mine can run 10.9 but I will give it a try. Thanks!

HookShot fucked around with this message at 20:10 on Apr 14, 2014

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
Oh, Xcode 5 does require 10.8 and I just misremembered. 10.8 has the same requirements as 10.9 so I guess if you can't run 10.9 you do need a new machine.

HookShot
Dec 26, 2005
Ah ok, thanks!

lord funk
Feb 16, 2004

:shepicide:

At launch, I perform a scan of the user's documents folder where I openWithCompletionHander: a bunch of documents, cache some important information (like 'tags' for sorting / searching), and close them. As is probably obvious, this takes gently caress-all forever. With 256 files in the documents folder (not unreasonable) it takes 30s.

As I see it, I need one of these solutions:
1). Find a way to really speed up the opening / caching of file metadata
2). Find a way to scan that file data without opening the file

I so need a fix for this, and I'm so out of ideas.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

lord funk posted:

:shepicide:

At launch, I perform a scan of the user's documents folder where I openWithCompletionHander: a bunch of documents, cache some important information (like 'tags' for sorting / searching), and close them. As is probably obvious, this takes gently caress-all forever. With 256 files in the documents folder (not unreasonable) it takes 30s.

The usual model would be to cache the metadata after you extract it, along with modification time, and then only rescan if that time changes.

The other opportunity is to parallelize the scanning, since even SSD I/O is really slow compared to computation. Scheduling that I/O better could help a lot when you do have to scan (like at first startup).

Edit: (100ms per file does seem like a lot, though, unless the files are really large, so there may be opportunity there as well.)

lord funk
Feb 16, 2004

Subjunctive posted:

Edit: (100ms per file does seem like a lot, though, unless the files are really large, so there may be opportunity there as well.)
My first thought too, and it's been checked. The actual scanning and caching is quick: 200ms total for the entire batch. What seems to be slowing it down is the queuing of the file I/O on the main thread. The app is responsive, but things that are dispatched to the main queue have to wait until the entire scan is done. One of my views sits mostly empty the entire time just waiting its turn. :(

Here is an Instruments time profile that (I think) shows it's a queuing / I/O thing:


Subjunctive posted:

The other opportunity is to parallelize the scanning, since even SSD I/O is really slow compared to computation. Scheduling that I/O better could help a lot when you do have to scan (like at first startup).

How is this done?

dupersaurus
Aug 1, 2012

Futurism was an art movement where dudes were all 'CARS ARE COOL AND THE PAST IS FOR CHUMPS. LET'S DRAW SOME CARS.'

dupersaurus posted:

I'm trying to hack in custom URL schemes to my Unity app, I'm having a couple of issues, and I really have no idea what to do about it.

1) I've setup and registered the scheme, and it works: every other time. This is for launching the app via web page, so I enter the url "myscheme://?params". A dialog opens up asking me if I want to open the app; I tap yes and nothing happens. I enter the url again, and it jumps right to the app.

2) If the app has to be launched, the didFinishLaunchingWithOptions delegate is called and I can get the url from there, and I return YES from it. But the openURL delegate is never called (it's in the same class), whether the app is starting fresh or if it's in the background.

FYI, Unity generates a UnityAppController class that implements UIApplicationDelegate, which is where I'm putting all this in (for now). I'm still very new to iOS development so I don't really know what I'm doing, but as far as I can tell I'm not missing anything. Any ideas I can try?

For the sake of sharing the knowledge, I managed to figure this out:

1) We're using Facebook's official Unity SDK, which also uses custom url scheme to handle authenticating with the app, which was implementing openURL with their AppController implementation. So I had to hack a check looking for my scheme before going to the facebook scheme. I should have noticed that earlier.

2) Automatically redirecting to the link doesn't work, but having the user click a link to it does.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

lord funk posted:

How is this done?

I haven't done it with UIDocument, but I suspect that your current pattern is openWithCompletionHandler: -> yourHandler -> openWithCompletionHandler: ... -- each handler queues the next document. Instead you could fire all the openWithCompletionHandler: calls at once, and then proceed with the rest of the app's work once they've all had their handlers fire.

lord funk
Feb 16, 2004

Subjunctive posted:

I haven't done it with UIDocument, but I suspect that your current pattern is openWithCompletionHandler: -> yourHandler -> openWithCompletionHandler: ... -- each handler queues the next document. Instead you could fire all the openWithCompletionHandler: calls at once, and then proceed with the rest of the app's work once they've all had their handlers fire.

I'm not waiting for each completion handler to set up the next one. In case it helps, here's the code.

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

lord funk posted:

I'm not waiting for each completion handler to set up the next one. In case it helps, here's the code.

Hmm, right, openWithCompletionHandler doesn't do the read, just the open. I guess it could be in the addDocumentMetadataToLiveData path, but I'm pretty far into guesswork now. What's under the coordinateReadingItem tree?

Hughlander
May 11, 2005

So uhh...

Apparently, WWDC notices can go to the Spam folder in gmail.

And I've had one there since the 7th...
With a reminder on the 9th to buy it.
With a final reminder yesterday that I have until 5p today to buy it.
Got it with 90 minutes to spare.

Guess who's going to his 2nd WWDC in a row?

CHECK THOSE SPAM FOLDERS

lord funk
Feb 16, 2004

Subjunctive posted:

What's under the coordinateReadingItem tree?

GOLD is what. The NSFileCoordinator uses readFromURL:error: to pop open the files. Skipping the NSFileCoordinator (against the advice of Apple) speeds the read WAY up.

Doctor w-rw-rw-
Jun 24, 2008

Hughlander posted:

So uhh...

Apparently, WWDC notices can go to the Spam folder in gmail.

And I've had one there since the 7th...
With a reminder on the 9th to buy it.
With a final reminder yesterday that I have until 5p today to buy it.
Got it with 90 minutes to spare.

Guess who's going to his 2nd WWDC in a row?

CHECK THOSE SPAM FOLDERS

I'm going to use a coworker's badge. See you there!

lord funk posted:

My first thought too, and it's been checked. The actual scanning and caching is quick: 200ms total for the entire batch. What seems to be slowing it down is the queuing of the file I/O on the main thread. The app is responsive, but things that are dispatched to the main queue have to wait until the entire scan is done. One of my views sits mostly empty the entire time just waiting its turn. :(

Here is an Instruments time profile that (I think) shows it's a queuing / I/O thing:



How is this done?

- [NSFileHandle readToEndOfFileInBackgroundAndNotify]? It'll use background threads to read the files then send you a notification on the main thread with the NSData. Then you can (spitballing here), create a subqueue attached to a background queue, with a dispatch group that blocks on completion, and dispatch_async to a different background queue to process the NSData. Then when the group completes, take the collection, copy it to be immutable, and dispatch_async back to the main queue with your immutable and therefore threadsafe collection.

Of course, I'm prone to overengineering, but that would probably maximize use of background threads over the main thread, which last year trained me to think about.

Doctor w-rw-rw- fucked around with this message at 00:15 on Apr 15, 2014

Subjunctive
Sep 12, 2006

✨sparkle and shine✨

lord funk posted:

GOLD is what. The NSFileCoordinator uses readFromURL:error: to pop open the files. Skipping the NSFileCoordinator (against the advice of Apple) speeds the read WAY up.

Sweet.

I think Apple would recommend overriding readFromURL:error instead or something.

Hughlander
May 11, 2005

Doctor w-rw-rw- posted:

I'm going to use a coworker's badge. See you there!

Cool, let's set up another lunch. Can even be a day you don't go if you want if you're downtown SF and not the valley.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
Should be a fun one. :)

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
I wanted to share an error message with you today; it is not often one hits upon an error message that has absolutely zero google hits. Only useless hits? Sure. But almost everything has at least one hit out there. Meet our friend SSErrorAllowBioAuthenticationKey.

2014-04-14 22:19:20.483 StormSim[3903:60b] [-[StoreManager paymentQueue:updatedTransactions:] +399]
Unable to purchase com.obsolete_software.StormSim.RainPack1:
Error Domain=SSServerErrorDomain
Code=1003 "Cannot connect to iTunes Store"
UserInfo=0x17026e9c0 {NSLocalizedDescription=Cannot connect to iTunes Store, SSErrorAllowBioAuthenticationKey=true}


Of course by posting this I have disturbed the system and this post will itself become the sole google hit for the error key. Hello future people looking for information about this error. I apologize, but you're boned!


edit: I'm a dummy, forgot to sign out of the store and login when prompted in the app instead.

Simulated fucked around with this message at 04:29 on Apr 15, 2014

BennyGsGhost
Jun 27, 2002

Low P/B or Bust
Pillbug
I have what is very likely a dumb question. I'm learning iOS development, and one problem I haven't been able to search up a good answer for is state preservation for a UITabBarController. I have one that is the root view controller for my extremely simple app. It holds on to two view controllers. I'm going through a iOS dev book (Big Nerd Ranch iOS dev) and I've set up the vc's to properly save their state.

The problem is when I try to restore the tab bar controller, it gives me a blank tab bar controller with neither of the tabs it had before. I've given the controller a restoration identifier and I have the app delegate provide a instance on restore, which is where I'm guessing my problem is - for some reason, I'm not getting the child view controllers the tab bar previously had on restore despite rebuilding with the proper "identifier components".

So I am guessing that I'm missing something here but I can't figure it out.

lord funk
Feb 16, 2004

The drop shadow during UITableView transitions got worse in 7.1. It only appears during the transition animation, and then disappears when its done. Anyone know where I can intercept this thing?

Screenshot mid-animation:

edit: going to try making a custom transition using -navigationController:animationControllerForOperation:

edit 2: yeah that worked great. You'd think I'd know by now that the correct answer is modify the provided interface roll your own.

Only registered members can see post attachments!

lord funk fucked around with this message at 19:29 on Apr 17, 2014

CapnAndy
Feb 27, 2004

Some teeth long for ripping, gleaming wet from black dog gums. So you keep your eyes closed at the end. You don't want to see such a mouth up close. before the bite, before its oblivion in the goring of your soft parts, the speckled lips will curl back in a whinny of excitement. You just know it.
I know not very much about iOS programming, but here's the deal: I've got an in-house application (so it's not on the app store, I distribute it in dev mode by having the people who use it bring their iPhones to me) that uses push services. We run a Windows application on the web server that reads a data queue and sends out the alerts as appropriate. When we added a bunch of new devices to the provisioning profile, the alerts stopped working. After tearing my hair out for months because I know basically nothing about iOS and was learning what I knew on the fly, I eventually fixed it by revoking the old certificate, generating a new one using the updated provisioning profile, downloading that new certificate, getting a .p12 file from it, and giving that .p12 to the Windows application.

Now we've added a few new devices and, wouldn't you know it, alerts have stopped working again. My question is simple: Do I seriously have to do this every time we add a new device? It's an immense pain in the rear end.

fankey
Aug 31, 2001

moved to C/C++ thread since I think it's more of a POSIX sockets issue...

fankey fucked around with this message at 21:23 on Apr 18, 2014

kitten smoothie
Dec 29, 2001

CapnAndy posted:

I know not very much about iOS programming, but here's the deal: I've got an in-house application (so it's not on the app store, I distribute it in dev mode by having the people who use it bring their iPhones to me) that uses push services. We run a Windows application on the web server that reads a data queue and sends out the alerts as appropriate. When we added a bunch of new devices to the provisioning profile, the alerts stopped working. After tearing my hair out for months because I know basically nothing about iOS and was learning what I knew on the fly, I eventually fixed it by revoking the old certificate, generating a new one using the updated provisioning profile, downloading that new certificate, getting a .p12 file from it, and giving that .p12 to the Windows application.

Now we've added a few new devices and, wouldn't you know it, alerts have stopped working again. My question is simple: Do I seriously have to do this every time we add a new device? It's an immense pain in the rear end.

You can screw with that or you can just pay $200 more and distribute the "right" way by signing them as enterprise apps rather than adding them to your developer account as test devices.

https://developer.apple.com/programs/ios/enterprise/

CapnAndy
Feb 27, 2004

Some teeth long for ripping, gleaming wet from black dog gums. So you keep your eyes closed at the end. You don't want to see such a mouth up close. before the bite, before its oblivion in the goring of your soft parts, the speckled lips will curl back in a whinny of excitement. You just know it.

kitten smoothie posted:

You can screw with that or you can just pay $200 more and distribute the "right" way by signing them as enterprise apps rather than adding them to your developer account as test devices.

https://developer.apple.com/programs/ios/enterprise/
But that definitely is the only way to do it unless we spend the $200? Because I think I can make the case for that money if the alternative is "or the goddamn things break every time we add a device".

dupersaurus
Aug 1, 2012

Futurism was an art movement where dudes were all 'CARS ARE COOL AND THE PAST IS FOR CHUMPS. LET'S DRAW SOME CARS.'
There's also something like TestFlight, but again, that's kind of like hacking around the real solution.

lord funk
Feb 16, 2004

lord funk posted:

...custom transition using -navigationController:animationControllerForOperation: ...

So this is great until the table view is loaded with a bunch of cells, then it chugs like crazy. The default Apple transition with the drop shadow is totally smooth.

Here's the entire animateTransition method. Anyone see a glaring animation optimization issue?

Objective-C code:
- (void)animateTransition:(id<UIViewControllerContextTransitioning>)transitionContext {
    UIViewController *toViewController = [transitionContext viewControllerForKey:UITransitionContextToViewControllerKey];
    UIViewController *fromViewController = [transitionContext viewControllerForKey:UITransitionContextFromViewControllerKey];
    [[transitionContext containerView] addSubview:toViewController.view];
    
    toViewController.view.alpha = 0;
    toViewController.view.transform = CGAffineTransformMakeTranslation(fromViewController.view.bounds.size.width, 0);

    [UIView animateWithDuration:[self transitionDuration:transitionContext] delay:0.0 options:UIViewAnimationOptionCurveEaseOut animations:^{
        fromViewController.view.transform = CGAffineTransformMakeTranslation(-80, 0);
        fromViewController.view.alpha = 0;
        toViewController.view.transform = CGAffineTransformIdentity;
        toViewController.view.alpha = 1;
    }
                     completion:^(BOOL finished) {
                         fromViewController.view.transform = CGAffineTransformIdentity;
                         [transitionContext completeTransition:![transitionContext transitionWasCancelled]];
                     }];
}
I based it on this objc.io post.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
What does Instruments say?

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"
I'm having some problems with a recursive block (gross) used in async call to do a web request. Here's my code:

code:
- (void) getURL_:(NSString *) url
      parameters:(NSDictionary *) parameters
      authorized:(BOOL) authorized
        retrying:(BOOL) retrying
           block:(void (^)(UNIHTTPJsonResponse *, NSError *)) block {
  
  UNIResponseHandler responseHandler = ^(UNIHTTPJsonResponse *response, NSError *error) {
    NSLog(@"%d", response.code);
    if (authorized && response.code == 403) {
      if (!retrying) {
        NSLog(@"First 403");
        // We're getting a 403 for the first time. Most likely the access token expired,
        // so refresh it and try the request again.
        [self refreshAccessToken_:^{
          [self getURL_:url
             parameters:parameters
             authorized:authorized
               retrying:YES
                  block:responseHandler];
        }];
      } else {
        // We got a 403 twice, even after refreshing the token. Don't retry, just report
        // the error.
        NSLog(@"Second 403: %@", response.body.description);
      }
    } else {
      // ***
      // THIS LINE GIVES ME EXC_BAD_ACCESS, but only in cases when it goes through the
      // retry flow
      // ***
      block(response, error);
    }
  };

  [[UNIRest get:^(UNISimpleRequest *request) {
    request.url = [self requestURL_:url];
    request.headers = authorized ? self.authorizedRequestHeaders_ : self.requestHeaders_;
    request.parameters = parameters;
  }] asJsonAsync:responseHandler];
}
It's OAuth, so the idea is that if the request being made needs to be authorized, it tries it once, and if it gets a 403 back, it refreshes the access token and tries again.

Problem is, I get EXC_BAD_ACCESS when it tries to call "block" the second time through that flow. I'm pretty sure that ARC is garbage collecting my poo poo by the time it makes it to that second attempt, and I've tried putting [block copy] in various places to try to fix it, but nothing I've done works. I'm stumped. Any suggestions?

haveblue
Aug 15, 2005



Toilet Rascal
It looks like none of the places the block is being stored count as strong references, so ARC is dropping it even with the copy call. Try making it a strong property of the instance for the duration of the request.

Plorkyeran
Mar 22, 2007

To Escape The Shackles Of The Old Forums, We Must Reject The Tribal Negativity He Endorsed
The block being assigned to responseHandler is capturing the value of the variable at the time the block is created, which is before that block is assigned to the variable. The simple fix is to make it a __block variable and then break the retain cycle by setting it to nil at the end of the block, but I don't see why you're even passing responseHandler to the recursive call -- AFAICT you should just be passing block.

lord funk
Feb 16, 2004

pokeyman posted:

What does Instruments say?

Looks like animating the views' alpha property causes it to be rendered offscreen, which is why it's slowing down. I know there's a way around this but on 1 hour of sleep I'm beat.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"

haveblue posted:

It looks like none of the places the block is being stored count as strong references, so ARC is dropping it even with the copy call. Try making it a strong property of the instance for the duration of the request.

I considered this, but since I might have multiple requests going off at once, tracking those blocks could be a pain.

Plorkyeran posted:

The block being assigned to responseHandler is capturing the value of the variable at the time the block is created, which is before that block is assigned to the variable. The simple fix is to make it a __block variable and then break the retain cycle by setting it to nil at the end of the block, but I don't see why you're even passing responseHandler to the recursive call -- AFAICT you should just be passing block.

Thanks! I'll try this later tonight.

I'm passing responseHandler to the recursive call because I want to be able to handle the case where I get a second 403 error -- if the user has revoked access to my app and I can't get a new access token (though I could probably handle this in the refreshAuthToken_ method), or if the user is just trying to access something they legitimately don't have access to, I don't want to call block right away (if at all).

Doctor w-rw-rw-
Jun 24, 2008

lord funk posted:

Looks like animating the views' alpha property causes it to be rendered offscreen, which is why it's slowing down. I know there's a way around this but on 1 hour of sleep I'm beat.

That strikes me as possibly incorrect?

In any case, setting hidden = YES should make the view hierarchy for the views you want to have 0 alpha not render. UIViewControllers usually remove or hide (not sure which) when they're not on top, but that is not necessarily the case for custom transitions.

Plorkyeran
Mar 22, 2007

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

Flobbster posted:

I'm passing responseHandler to the recursive call because I want to be able to handle the case where I get a second 403 error -- if the user has revoked access to my app and I can't get a new access token (though I could probably handle this in the refreshAuthToken_ method), or if the user is just trying to access something they legitimately don't have access to, I don't want to call block right away (if at all).
That's already covered by the retrying parameter. If the first request succeeds, you call block immediately. If the second request succeeds, passing responseHandler rather than block results in you checking the same request for success twice, and then calling block. If the second request fails, the passed block is never called at all, so it doesn't matter which you'd passed.

Flobbster
Feb 17, 2005

"Cadet Kirk, after the way you cheated on the Kobayashi Maru test I oughta punch you in tha face!"

Plorkyeran posted:

That's already covered by the retrying parameter. If the first request succeeds, you call block immediately. If the second request succeeds, passing responseHandler rather than block results in you checking the same request for success twice, and then calling block. If the second request fails, the passed block is never called at all, so it doesn't matter which you'd passed.

Ah yeah, I see it now. The responseHandler that ends up handling the second attempt is the one that is created locally in the second recursive call, not the one that I pass in to make that call.

This is what happens when I code all day for work and then try to spend my evenings working on a personal project while I fight sleep :psyduck:

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer

CapnAndy posted:

But that definitely is the only way to do it unless we spend the $200? Because I think I can make the case for that money if the alternative is "or the goddamn things break every time we add a device".

The Enterprise Program 100% worth it if you're dicking around with your device list with any regularity. The enterprise cert lets you sign something and it "just works" on any device that can get the IPA.

Doctor w-rw-rw-
Jun 24, 2008
Just a heads-up to iOS devs, if you like responsive and high-performance user interfaces, you might want to catch the F8 conference livestream on April 30th, from 3:45 PM to 4:30 PM. Specifically, Mobile Engineering at Facebook's Scale. There should be a pretty interesting segment.

Adbot
ADBOT LOVES YOU

kitten smoothie
Dec 29, 2001

ultramiraculous posted:

The Enterprise Program 100% worth it if you're dicking around with your device list with any regularity. The enterprise cert lets you sign something and it "just works" on any device that can get the IPA.

Yeah. My team has two Apple developer program accounts, one for the App Store and one enterprise.

We build nightly internal dogfood versions of our app, sign them with the enterprise cert, and publish those to TestFlight for internal use. Anyone who wants in on the dogfood builds can get it that way and it is a ton easier.

There's also a way to craft an HTML link that triggers Safari to offer to download and install an IPA over the air. If you didn't want to use a distribution service like TestFlight you could put that on your intranet or a Dropbox link or something.

kitten smoothie fucked around with this message at 15:06 on Apr 19, 2014

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