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
Doh004
Apr 22, 2007

Mmmmm Donuts...

PT6A posted:

EDIT: Are you using SSL to secure profiles or anything? If so, you will have to go through the ORDEAL OF PAIN with the US government to get export compliance or some weird paranoid yankee poo poo.

Naw, we don't have any personal sensitive information. Aside from allowing people to submit their contacts to our website, the app doesn't really handle any other information, just regurgitating JSON.

Thanks for the advice though.

Adbot
ADBOT LOVES YOU

PT6A
Jan 5, 2006

Public school teachers are callous dictators who won't lift a finger to stop children from peeing in my plane

Doc Block posted:

I was under the impression you don't need to seek export permission if you're using the built-in crypto libraries (including SSL), since Apple has already gone ahead and gotten export permission for those.

Otherwise there are thousands and thousands of apps in violation: every app that uses Facebook's SDK, an OAuth library, Flurry, etc.

My understanding is that you don't need a full CCATS but you do need an ERN. I could be mistaken, though. It's very hard to find anything conclusive either way. I'm not sure where the dividing line is between using another library and being considered to have done it yourself. If you call a library function it might be okay, but if you make a HTTPS request to a REST resource perhaps not. Do you have any suggested reading on the subject?

Zhentar
Sep 28, 2003

Brilliant Master Genius
IANAL, but if the code that performs the encryption is not compiled into your binary, then I don't see how you could be exporting encryption.

PT6A
Jan 5, 2006

Public school teachers are callous dictators who won't lift a finger to stop children from peeing in my plane

Zhentar posted:

IANAL, but if the code that performs the encryption is not compiled into your binary, then I don't see how you could be exporting encryption.

From what I've heard, it's because the law doesn't differentiate between "contains encryption" and "uses encryption." There is evidently a streamlined process to get approval for a product which does not actually itself contain the code, but based on what I've read I still think it's necessary.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
Pro tip #92834: Use Instruments to automate your UI testing and/or screenshot taking. Would you like to know more?


First, create a UtilityScripts.js file in your Xcode workspace (so it will get checked into source control and versioned... you will cry bitter, bitter tears if all this hard work gets eaten). Here is a good basic set of utility functions:

code:
var target = UIATarget.localTarget();
var app = target.frontMostApp();
var mainWindow = app.mainWindow();
var tabBar = mainWindow.tabBar();

function withOrientation(orientation, func) {
    target.delay(2.0);
    var oldOrientation = target.deviceOrientation();
    UIALogger.logMessage("current device orientation: " + oldOrientation);
    target.setDeviceOrientation(orientation);
    target.delay(4.0);
    try {
        func();
    }
    finally {
        target.delay(2.0);
        target.setDeviceOrientation(oldOrientation);
        target.delay(2.0);
    }
}


function runTest(doRun, name, func, options) {
	if(!doRun) return;
    if(options == null) {
		options = {
            logTree: true
		};
	}
    
    UIALogger.logStart(name);
    try {
        func(name, options);
        UIALogger.logPass(name);
    }
    catch(e) {
        UIALogger.logError(e);
        if(options.logTree)
            target.logElementTree();
        UIALogger.logFail(name);
    }
}
First we setup some shortcut vars to common things, then we setup a helper function to change orientations, then finally a test runner method that will log the tree of UI elements on failure, as well as indicate success/fail to UIAutomation so we get fancy green/red indicators for pass/fail in the Instruments UI.


Now go to Xcode, Product, Profile (or Command-I). Select the Automator template. Save the Instruments setup or you'll regret it; I also recommend checking "Continuously Log Results" and make sure the folder you select is where you placed your Instruments file. Screenshots will appear inside Instruments but if you attempt to open them in Preview or do anything with them they'll show as unreadable/corrupted unless you follow this advice. Wherever you save this, there will be subfolders created for each Instruments run and that's where you will find the screenshots written as PNGs, so make sure you create separate folders for different projects/etc or they'll end up all mixed up. Good news is you can use the Simulator in Retina mode and it will grab good screenshots, even if the simulator is showing up as scaled or whatever. This is really helpful for iPad Retina screenshots as almost no one can fit that whole thing on the screen. Also doesn't matter if the simulator window is covered up - it grabs the backing buffer directly.

On the left, under Scripts, click Add, then Create Script. Give it a name like Screenshots.js. Note: Instruments will continuously save this file without prompting so don't open it in another editor while Instruments is open. If you import a script it gets copied over, so far I haven't found a way to reference a file in source control without copying it so watch out for backing up your scripts. You can certainly add your tests to another file in Xcode, then have your Instruments script just call one main() function in there.

What, pray tell, will we do with this script?

code:
#import "/full/path/to/xcode/project/TestScripts/Utilities.js"

var CLOCK = 0;
var NOWPLAYING = CLOCK + 1;
var LIBRARY = CLOCK + 2;
var OPTIONS = CLOCK + 3;
var STORE = CLOCK + 4;

target.delay(4.0);
The first thing is to include Utility.js from your workspace in this script, which confusingly has nothing to do with the import command in the Instruments UI. Next I setup constants for my UI tabs. It's a good idea to have each test/screenshot function explicitly navigate to the place it wants to be in the UI, then navigate back to the root so you can keep things sensible... otherwise you will have very painful order-of-execution issues without realizing it.

Now one important thing to remember for screenshots is that UIAutomation doesn't necessarily wait for animations to complete, so you may need to insert delays to prevent your screenshots from being jacked up, so I've got a target.delay(4.0) item in there to pause and wait for my app to truly finish starting up. UIAutomation tries to wait for some things, e.g.: if you tell a table cell button to "tap" then try to grab the new table view sliding onto screen, it will wait for that new view controller to setup, then display it's table view, but in my experience anything involving screenshots just required me to manually inject delays, otherwise the screenshots were a mess.


code:
runTest(true, "clockShot", function() {
	withOrientation(UIA_DEVICE_ORIENTATION_LANDSCAPERIGHT, function() {
		tabBar.buttons()[CLOCK].tap();
		target.delay(2.0);
		target.captureScreenWithName("001-ClockScreenshot");
	});
});
Ah here is our first test. The true/false parameter lets me quickly disable a test without having to comment out the code. "clockShot" is the name of the test displayed in Instruments.
I'm using the orientation helper function to make sure we switch to landscape orientation for the duration of the test, then switch back to whatever it was originally (portrait) when done. Then I find the clock button on the tab bar and tap it. This selects the clock view, and I wait 2 seconds to make sure any animations are done. Then I capture a screenshot which will be named "001-ClockScreenshot.png" and placed in the "/path/to/instruments/file/Run XYZ" folder. Note: Orientation stuff is sometimes flaky so watch out, you may need to re-run the test or manually fuss with the simulator to get it to work properly.

Now let's get into something a bit more interesting:
code:
runTest(false, "optionsWakeTimer", function() {
		tabBar.buttons()[OPTIONS].tap();
		target.delay(1.0);
		var table = mainWindow.tableViews()[0];
		var cell = table.cells()[2];
		cell.tap();
		target.delay(1.0);
		table = mainWindow.tableViews()[0];
		cell = table.cells()[0];
		cell.switches()[0].tap();
		target.delay(1.0);
		target.captureScreenWithName("005-WakeTimer");
});
OK here you can see how you can manipulate the UI element tree to locate controls. I grab the first available table view (usually only one unless on iPad), then grab the third cell (index 2) and tap it. Then I re-grab the table view because the view hierarchy has changed. I locate the first cell, grab the first switch control, then tap it.

Notice something? Almost all the element traversal is accomplished with a JS function that returns a UIAElementArray containing any elements that matched the request. There are a variety of predicates you can use to do all sorts of fancy things, for example table.cells().firstWithName("xyz")... in this case it uses the Accessibility name to locate the first cell matching "xyz". You can also do things like withPredicate("someprop begins with 'x'") which would return all controls where a property "someprop" is a string starting with the character "x". You can discover the types of the elements (typeof(cell) == UIATableCell), etc.

In my case, since I am switching the simulator language to capture all the localized screenshots I can't use the name as that is localized as well, so I navigate by indexes. It's definitely more brittle but instead of manually setting up ((5x iPhone3.5") + (5x iPhone4") + (5x iPad)) x 6 languages x (free+paid) = 180 screenshots, I can narrow that down into a much smaller set of runs. Once you stop recording in Instruments it kills the app, then you can switch the simulator hardware (Target, Options, Simulator Hardware to switch iOS versions or iPhone vs iPad... retina vs non-retina just use the Simulator Hardware menu) and hit Record again no problem. Same deal with switching languages - stop recording, go to Settings, General, International, Language in the simulator and it will reboot the simulator in another language. Now hit Record and Bam! localized screenshots. With this setup I only have to do 36 things and the screenshots all turn out identical with no mistakes (6 language changes, three hardware changes, two apps) and those things are considerably faster.

You can find the complete JS reference here: UIAutomation JS Reference. Most of the actual UI elements like tables, buttons, etc derive from UIAElement so start there for some interesting things. UIAElementArray is another good one and has all the find/firstWith/etc methods.


I've included a screenshot of what this looks like after running; the green indicates pass, but the first one shows red because of a failure. Notice how you can navigate the UI hierarchy and see just the listed control on the right under "Screenshot". I just did this for show, right now I'm not using it for testing so much as screenshots but my next project will definitely include some tests so I can get repeatable test cases.

Only registered members can see post attachments!

Simulated fucked around with this message at 17:21 on Dec 1, 2012

Glimm
Jul 27, 2005

Time is only gonna pass you by

PT6A posted:

and submit them a bug-free product

Someday I hope to do this.

Zhentar
Sep 28, 2003

Brilliant Master Genius

PT6A posted:

From what I've heard, it's because the law doesn't differentiate between "contains encryption" and "uses encryption." There is evidently a streamlined process to get approval for a product which does not actually itself contain the code, but based on what I've read I still think it's necessary.

The guv'ment would agree with you, apparently. http://www.bis.doc.gov/encryption/flowchart1.pdf

lord funk
Feb 16, 2004

Design question. I have a custom view I'm loading into UITableViewCells. Each corresponds to a model object that can be edited / re-ordered / deleted. My question is: where would you put the view controller(s) for the custom views (in red) in this setup?

I have some thoughts of my own, but I'd rather hear some opinions first.

Froist
Jun 6, 2004

lord funk posted:

Design question. I have a custom view I'm loading into UITableViewCells. Each corresponds to a model object that can be edited / re-ordered / deleted. My question is: where would you put the view controller(s) for the custom views (in red) in this setup?

I have some thoughts of my own, but I'd rather hear some opinions first.



I may be overlooking something here, but I'd probably just create the view controller as a member of the table cell, then add its owned view as a subview of the cell?

Filburt Shellbach
Nov 6, 2007

Apni tackat say tujay aaj mitta juu gaa!
My second app landed in the store today. :sun:

duck monster
Dec 15, 2004

Doc Block posted:

I was under the impression you don't need to seek export permission if you're using the built-in crypto libraries (including SSL), since Apple has already gone ahead and gotten export permission for those.

Otherwise there are thousands and thousands of apps in violation: every app that uses Facebook's SDK, an OAuth library, Flurry, etc.

....or UIWebView for that matter

Doh004
Apr 22, 2007

Mmmmm Donuts...
Once your app is approved and on the store, do updates take (potentially) as long to be approved?

Say we're a week in to the app being out, and our server side folks push out an emergency update to our production environment which makes the app not work correctly. Does Apple ever expedite the process? If not, how do you guys handle situations like that?

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

Doh004 posted:

Once your app is approved and on the store, do updates take (potentially) as long to be approved?

Say we're a week in to the app being out, and our server side folks push out an emergency update to our production environment which makes the app not work correctly. Does Apple ever expedite the process? If not, how do you guys handle situations like that?

Well first off you should have some kind of API versioning and use an app-specific DNS name so you can handle these kinds of situations. For example if you are just using the regular REST service right now you should still point to mobileapi.yoursite.com/v1/ so if you need to keep an older version of your app server/etc going you can do so, and then if you need to make a breaking change deploy at /v2/ so non-upgraded clients will keep working. About half my users upgrade within 48 hours but the rest trail off over several months.

Second, updates generally take about the same or less time but it is highly variable. If you just fixed one bug and note that in the app review comments you might get a faster look but that's more likely during new product releases (eg: "updates for iPhone 5") would get you fast-tracked in the month after iPhone 5 came out. Right now I'm seeing about a week to review, give or take.

There is an expedited review request you can do for emergency fixes, but if you use it too much Apple will ignore them; I'd say not more than once every year per app, if that. If you use it as a substitute for not having API versioning, not properly bug testing, etc then you can expect future expedite request to get automatically poo poo-canned.

For reference I used it the first time several months ago for an app that has been out over a year. They approved the expedite request and got my update posted the next day.

Doh004
Apr 22, 2007

Mmmmm Donuts...

Ender.uNF posted:

Well first off you should have some kind of API versioning and use an app-specific DNS name so you can handle these kinds of situations. For example if you are just using the regular REST service right now you should still point to mobileapi.yoursite.com/v1/ so if you need to keep an older version of your app server/etc going you can do so, and then if you need to make a breaking change deploy at /v2/ so non-upgraded clients will keep working. About half my users upgrade within 48 hours but the rest trail off over several months.

We had talked about versioning it, but fortunately we don't think that will be completely necessary. Our app is the only thing using it, and anything emergency patch that we'd have to do (we shouldn't) we'll make sure to do our due diligence and test out the app. For the long term, when we're not just trying to get the app out there, we'll have more time and resources to implement this. One stop measure that we're gonna add for sure right now is to pass in the app version along with each request. That way, if we need to change the way the data is returned for the app based off of an older version, we'll have the ability to add in some checks.

Good to know about the expedited requests though, thanks.

vapid cutlery
Apr 17, 2007

php:
<?
"it's george costanza" ?>

PT6A posted:

My understanding is that you don't need a full CCATS but you do need an ERN. I could be mistaken, though. It's very hard to find anything conclusive either way. I'm not sure where the dividing line is between using another library and being considered to have done it yourself. If you call a library function it might be okay, but if you make a HTTPS request to a REST resource perhaps not. Do you have any suggested reading on the subject?

I think the app submission process contains a line of questioning for this exact situation. It asks you if your app has encryption, then from there you can specify what type, and depending on what kind of encryption you use you don't have to provide any additional materials.

vapid cutlery
Apr 17, 2007

php:
<?
"it's george costanza" ?>
Regarding app review times, this page https://developer.apple.com/appstore/resources/approval/index.html has information about current processing times for new submissions and updates, on the right hand side. It's only accessible through a developer account.

tarepanda
Mar 26, 2011

Living the Dream
How does Apple look upon things like entering codes to unlock functionality when said codes are sold outside of the iOS system?

Doctor w-rw-rw-
Jun 24, 2008

tarepanda posted:

How does Apple look upon things like entering codes to unlock functionality when said codes are sold outside of the iOS system?

If you have an in-app signup/registration flow for a subscription service, they'd probably ban you.
If you have an in-app referral to "Sign up on ???.com" for a service which has a notable paid offering, they'd probably ban you.
If you have an in-app upsell to unlock the functionality which doesn't involve using in-app purchases, they'd probably ban you.

Source: experience. Took us a loving year of experimentation until we were confident enough to update our grandfathered-in main app (as opposed to testing the waters with other apps).

Doc Block
Apr 15, 2003
Fun Shoe
I think ban is a bit too harsh of a word. They'd just reject the update that added whatever they didn't approve of.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
Yeah, they basically want you to use the in-app purchasing. If the codes are explicitly just to enable stuff in the app and bypass Apple that's a no-go (and really annoying for users).

If the functionality can be purchased by tapping Buy in the app using IAP *or* by entering a code it should be OK.

duck monster
Dec 15, 2004

Apple are cruising for a kicking by the various countries competition watchdogs with their insistance on only allowing their own 30% appletax in-app purchasing system.

lord funk
Feb 16, 2004

Froist posted:

I may be overlooking something here, but I'd probably just create the view controller as a member of the table cell, then add its owned view as a subview of the cell?

Yeah, this is along the lines of what I was thinking. I watched the WWDC video on view controllers, and for a while thought I should be wedging these in as child view controllers, but I don't think I need the viewWillAppear viewDidAppear methods. So far it's working well.

lord funk
Feb 16, 2004

I posted this in the screenshots thread:



I just finished optimizing the drawing. I couldn't figure out why I was only getting 35 fps. Turns out I was only calling setNeedsDisplay every 0.03 seconds, so it would only be 35. :haw:

fankey
Aug 31, 2001

Is there any documentation on exactly how UIImage frees up memory in low memory situations? I have a case where I'd really like it to discard the internal image data ( as per the docs ) but as far as I can tell it never frees any memory and my app crashes when run on an iPad 1.

My app dynamically loads pages of content off a server on the network. The set of pages is user defined and contains controls like faders, knobs and meters as well as graphic elements like text and images. In the case of images the app downloads the images via HTTP to a local /tmp directory and then creates UIImages using imageWithContentsOfFile:. The resultant UIImage is set as the .image of a UIImageView and that set as a subView of a UIView used for the page. Each of the page UIViews are loaded into a UIScrollView. The UIScrollView is 'virtualizing' - it dynamically adds and remove content based on what page is currently visible. Right now it's configured to load 3 pages on each side of the current page.

In the particular case I'm trying to debug the user has created a set of 52 pages, each one with a 1024x768 png image on them. I download all of the images and create my pages without an issue. As I scroll through the pages, at some point ( around page 43 or so ) I get an out of memory warning and then it crashes. I know that it wouldn't be possible to load 52 pngs of that size on an iPad 1 so that's why I was hoping that the UIImages would discard their data when not visible as I scrolled through - as far as I can tell that's not happening.

I thought maybe the fact I am removing pages from the view tree was somehow screwing up the UIImage memory management stuff but if I disable my virtualization of the UIScrollView and just load all the images at once it immediately runs out of memory. Of course that doesn't mean what I'm doing isn't causing a problem but it does show that I'll need to do something to make this work.

Any idea why my approach isn't working?

Doc Block
Apr 15, 2003
Fun Shoe
You're unloading the pages once the user is past them, right? I think you said your app keeps 3 pages on each side, make sure they're getting unloaded once the user is far enough past them. You might not be unloading everything.

edit: I'm not super familiar with Instruments, but the Allocations instrument can tell you what is taking up all your memory.

Doc Block fucked around with this message at 20:11 on Dec 10, 2012

fankey
Aug 31, 2001

Doc Block posted:

You're unloading the pages once the user is past them, right? I think you said your app keeps 3 pages on each side, make sure they're getting unloaded once the user is far enough past them. You might not be unloading everything.

edit: I'm not super familiar with Instruments, but the Allocations instrument can tell you what is taking up all your memory.
Yes. I get the expected willMoveToWindow: with null for the window on the UIImageView as the user swipes through the pages - I believe that means I'm correctly unloading the pages once they get far enough past. Of course the documentation on UIImage memory management doesn't mention anything about needing the unload the images so I'm not sure if that would even be necessary.

I'm going to fire up Instruments next but I'm pretty much sure that I'm running out of memory because of the UIImages which is of no surprise if they aren't releasing memory under low memory situations.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
Are you absolutely certain you are removing the UIImageView from its super view and not holding a reference to it anywhere?

Instruments is really the answer... It should help you figure out what is sticking around.

fankey
Aug 31, 2001

Ender.uNF posted:

Are you absolutely certain you are removing the UIImageView from its super view and not holding a reference to it anywhere?

Instruments is really the answer... It should help you figure out what is sticking around.
I'm not removing the UIImageView directly from it's super view - there's a 4 view deep hierarchy between what I'm adding/removing from the UIScrollView and the UIImageView. As I said before, I am seeing the willMoveToWindow: on the UIImageView (with null as the newWindow) which I think means I'm removing it from the visual tree.

I am intentionally holding a reference to the UIImageView - I don't dealloc my 'removed' pages, I'm just removing them from the active UIView tree.

I guess I could be interpreting the documentation wrong.

quote:

In low-memory situations, image data may be purged from a UIImage object to free up memory on the system. This purging behavior affects only the image data stored internally by the UIImage object and not the object itself. When you attempt to draw an image whose data has been purged, the image object automatically reloads the data from its original file. This extra load step, however, may incur a small performance penalty.
Reading this, my hope was that the image data would be purged, hopefully on non visible UIImageViews, in low memory situations. Apparently I can't depend on that happening and will just have to clean up the UIImageViews as they get removed from the visual tree.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
It's probably the UIImageView holding onto the drawing buffer or something like that. You could try nil-ing out the image on the UIImageView which might get it to give up the goods.

IIRC the issue is that the CALayers are really OpenGL textures as far as the Quartz drawing engine is concerned so even if UIImage gives up its compresses PNG/JPG bytes you still have the texture buffer. I'm not personally clear on exactly under what circumstances a view will give up its layers and release that memory, I tend to either recycle the UIImageView (reposition it from off on the left to off on the right) or completely dealloc it. If you set things up that way, you'd only ever have a couple of UIImageView objects hanging around so it shouldn't cause any issues to swap their .image property in and out.

Doh004
Apr 22, 2007

Mmmmm Donuts...
Why does this white line appear at the top of my UINavigationBar when I set its tintColor?



code:
[[UINavigationBar appearance] setTintColor:[UIColor blackColor]];
I've set the background image to nil as well as the background color, but nothing.

*edit* It seems this is a standard. Do I have to set a custom background image instead?

Doh004 fucked around with this message at 22:38 on Dec 10, 2012

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.
Yes! It's your lucky day.

Don't forget UIAppearance proxies to make your life a bit easier sometimes.

e: I read good. You got it.

Doh004
Apr 22, 2007

Mmmmm Donuts...

pokeyman posted:

Yes! It's your lucky day.

Don't forget UIAppearance proxies to make your life a bit easier sometimes.

e: I read good. You got it.

Yeah, I ended up walking over to my designer with the device in hand and he goes "THIS LOOKS GREAT". So I guess the white line isn't an issue!

Doc Block
Apr 15, 2003
Fun Shoe

fankey posted:

I'm not removing the UIImageView directly from it's super view - there's a 4 view deep hierarchy between what I'm adding/removing from the UIScrollView and the UIImageView. As I said before, I am seeing the willMoveToWindow: on the UIImageView (with null as the newWindow) which I think means I'm removing it from the visual tree.

I am intentionally holding a reference to the UIImageView - I don't dealloc my 'removed' pages, I'm just removing them from the active UIView tree.

I guess I could be interpreting the documentation wrong.

Reading this, my hope was that the image data would be purged, hopefully on non visible UIImageViews, in low memory situations. Apparently I can't depend on that happening and will just have to clean up the UIImageViews as they get removed from the visual tree.

UIImageView converts the image you pass it into something that can be drawn quickly by the GPU. Which is where your problem is coming from: you aren't releasing the UIImageViews, so you're still running out of memory.

tarepanda
Mar 26, 2011

Living the Dream
I've been reading through in-app purchase tutorials and stuff and everyone's talking about getting lists of purchases and making a view for them and all that, which is just... too much for what we want.

Is it possible to just make a simple button in an existing view -- tap the button, buy the thing?

Doc Block
Apr 15, 2003
Fun Shoe
Unless it's a consumable item, you also need to have a Restore Purchases button.

Not sure how Apple will feel about having your Buy button be in a view with other, non-IAP stuff.

tarepanda
Mar 26, 2011

Living the Dream

Doc Block posted:

Not sure how Apple will feel about having your Buy button be in a view with other, non-IAP stuff.

Yeah, that's what I was worried about... and for a tablet app, it feels really, really dumb to have an entire view for one item.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
You can do that, you don't have to have a list. You can also stick the restore purchases button off in settings if you want. Apple will approve the app just fine.

Doh004
Apr 22, 2007

Mmmmm Donuts...
Do I need to include every single icon in the Icon Files value in my .plist? Like, do I have to specify Spotlight.png and Spotlight@2x.png or does it know to check for both like normal?

ManicJason
Oct 27, 2003

He doesn't really stop the puck, but he scares the hell out of the other team.
Apple's examples do both, so I've always done the same.

Adbot
ADBOT LOVES YOU

Doh004
Apr 22, 2007

Mmmmm Donuts...
Aight good to know, thanks. I'm hoping to get our initial submission in by EOD tomorrow :3:

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