Best iphone questions in October 2010

Fast and Lean PDF Viewer for iPhone / iPad / iOs - tips and hints?

48 votes

There has been many Questions recently about drawing PDF's.

Yes, you can render PDF's very easily with a UIWebView but this cant give the performance and functionality that you would expect from a good PDF viewer.

You can draw a PDF page to a CALayer or to a UIImage. Apple even have sample code to show how draw a large PDF in a Zoomable UIScrollview

But the same issues keep cropping up.

UIImage Method:

  1. PDF's in a UIImage don't optically scale as well as a Layer approach.
  2. The CPU and memory hit on generating the UIImages from a PDFcontext limits/prevents using it to create a real-time render of new zoom-levels.

CATiledLayer Method:

  1. Theres a significant Overhead (time) drawing a full PDF page to a CALayer: individual tiles can be seen rendering (even with a tileSize tweak)
  2. CALayers cant be prepared ahead of time (rendered off-screen).

Generally PDF viewers are pretty heavy on memory too. Even monitor the memory usage of apple's zoomable PDF example.

In my current project, I'm developing a PDF viewer and am rendering a UIImage of a page in a separate thread (issues here too!) and presenting it while the scale is x1. CATiledLayer rendering kicks in once the scale is >1. iBooks takes a similar double take approach as if you scroll the pages you can see a lower res version of the page for just less than a second before a crisp version appears.

Im rendering 2 pages each side of the page in focus so that the PDF image is ready to mask the layer before it starts drawing.Pages are destroyed again when they are +2 pages away from the focused page.

Does anyone have any insights, no matter how small or obvious to improve the performance/ memory handling of Drawing PDF's? or any other issues discussed here?

EDIT: Some Tips (Credit- Luke Mcneice,VdesmedT,Matt Gallagher,Johann):

  • Save any media to disk when you can.

  • Use larger tileSizes if rendering on TiledLayers

  • init frequently used arrays with placeholder objects, alternitively another design approach is this one

  • Note that images will render faster than a CGPDFPageRef

  • Use NSOperations or GCD & Blocks to prepare pages ahead of time.

  • call CGContextSetInterpolationQuality(ctx, kCGInterpolationHigh); CGContextSetRenderingIntent(ctx, kCGRenderingIntentDefault); before CGContextDrawPDFPage to reduce memory usage while drawing

  • init'ing your NSOperations with a docRef is a bad idea (memory), wrap the docRef into a singleton.

  • Cancel needless NSOperations When you can, especially if they will be using memory, beware of leaving contexts open though!

  • Recycle page objects by doing pointer swaps or destroy unused views

  • Close any open Contexts as soon as you don't need them

  • on receiving memory warnings release and reload the DocRef and any page Caches

Other PDF Features:

Documentation

I have build such kind of application using approximatively the same approach except :

  • I cache the generated image on the disk and always generate two to three images in advance in a separate thread.
  • I don't overlay with a UIImage but instead draw the image in the layer when zooming is 1. Those tiles will be released automatically when memory warnings are issued.

Whenever the user start zooming, I acquire the CGPDFPage and render it using the appropriate CTM. The code in - (void)drawLayer: (CALayer*)layer inContext: (CGContextRef) context is like :

CGAffineTransform currentCTM = CGContextGetCTM(context);    
if (currentCTM.a == 1.0 && baseImage) {
    //Calculate ideal scale
    CGFloat scaleForWidth = baseImage.size.width/self.bounds.size.width;
    CGFloat scaleForHeight = baseImage.size.height/self.bounds.size.height; 
    CGFloat imageScaleFactor = MAX(scaleForWidth, scaleForHeight);

    CGSize imageSize = CGSizeMake(baseImage.size.width/imageScaleFactor, baseImage.size.height/imageScaleFactor);
    CGRect imageRect = CGRectMake((self.bounds.size.width-imageSize.width)/2, (self.bounds.size.height-imageSize.height)/2, imageSize.width, imageSize.height);
    CGContextDrawImage(context, imageRect, [baseImage CGImage]);
} else {
    @synchronized(issue) { 
        CGPDFPageRef pdfPage = CGPDFDocumentGetPage(issue.pdfDoc, pageIndex+1);
        pdfToPageTransform = CGPDFPageGetDrawingTransform(pdfPage, kCGPDFMediaBox, layer.bounds, 0, true);
        CGContextConcatCTM(context, pdfToPageTransform);    
        CGContextDrawPDFPage(context, pdfPage);
    }
}

issue is the object containg the CGPDFDocumentRef. I synchronize the part where I access the pdfDoc property because I release it and recreate it when receiving memoryWarnings. It seems that the CGPDFDocumentRef object do some internal caching that I did not find how to get rid of.

How should I architect my iPhone app to talk to my website?

15 votes

I'm planning my first iPhone app and I'd like to get some inputs as to how to build it, right from the start. The iPhone app is being built to be paired with a public facing web application that is already built in PHP.

I'd like the web platform to be central (data is housed in a mySQL database), and have the iPhone clients talk to it and use REST'ful methods to perform the functions of the site (fetching latest content, posting content, voting, account management as examples).

I'd like the clients to get a local copy of the data in a SQLite database, but refresh to get the latest version of the feed (similar to the Twitter app).

Couple of thoughts I have right now:

  • Use something like ASIHTTPRequest to send/recieve data to PHP files on the server listening for requests

  • JSON - would I be better off to send the GET/POSTS to a PHP that returns JSON objects, and work with some sort of wrapper that manages the data and communicates changes to the local SQLite database?

  • Am I totally off in how I should be building this thing to communicate with the web? Is there a best practice for this?

I'd really appreciate any input on how you would architect this sort of a setup.

Thank you,

EDIT: After reading my own post again, I know it sounds like a Twitter client, but it is NOT, although it has similar features/structure of a Twitter type setup. Thanks!

As you already outlined in your plan, XML and REST are a great way to communicate with a web application. I want to suggest few details about how to actually design and build it, or what you should keep in mind.

First of all, I believe it's important to stick with MVC. I've seen people creating HTTP connections in view-controllers, controllers being NSXMLParser's delegate, controllers containing data in member variables. I've even seen UITableCells establishing HTTP connections. Don't do it!

Your model and its basic manipulation code should be as much extracted from user interface as possible. As you already have created the model in your web-application, try to recreate the entities in your iPhone project. Don't be afraid of having some simple methods in entity classes, but do not make them use external resources, especially tcp connections. As an example of methods in entity class you might have methods that formats data in specific ways (dates as an example, or returning fullname as concatenation of firstname and surname), or you can even have a method like - (void)update that would act as a wrapper to call class responsible to update the model.

Create another class for updating the model - fetching the XMLs from web-app. Do not even consider using synchronous connections, not even from a dedicated thread. Asynchronous connections with delegate is the way to go. Sometimes multiple requests need to be made to get all required data. You might want to create some kind of state-machine to keep the information about in which stage of downloading you are, and progress from stage to stage, skipping to the end if error occurs, re-executing from failed stage after some moments.

Download data somewhere temporarily, and first when you have it all, make a switch and update user interface. This helps responsiveness during launching the app - user gets to work immediately with data stored locally, while the update mechanism is downloading the new data.

If you need to download lots of files, try to download them simultaneously, if dependencies between files allow for that. This involves creating a connection per request, probably delegate instance for each of them. You can of course have only one delegate instance for all of those connections, but it gets a bit more complex to track the data. Downloading simultaneously might decrease latency considerably, making the mechanism much faster for the user.

To save the time and bandwidth, consider using HTTP's If-Modified-Since and/or ETag headers. Remember the time or tag when you requested the data the last time, and next time send it in HTTP's header. Your web-application should return HTTP code 304 if content has not been changed. iPhone app should react on this code accordingly in connection:didReceiveResponse:.

Create a dedicated class to parse the XML and update the model. You can use NSXMLParser, but if your files are not huge I strongly recommend TouchXML, it's such a pleasure to work with XML as document (it also supports XPath), instead of an event based API. You can use this parser also when files are downloaded to check their validity - re-download if parsing fails. That's when dedicated class for parsing comes handy.

If your dataset is not huge, if you do not need to persist downloaded data on iPhone forever, you probably don't need to store them in SQLite database, you can simply store them in XML format - just a simple caching. That at least might be the way for a twitter app. It gets easier that way, but for bigger data sets XML consumes lots of memory and processing power - in that case SQLite is better.

I'd suggest using Core Data, but you mention this is your first iPhone app, so I suggest you don't use it. Yet.

Do not forget about multitasking - your app can go to sleep in the middle of download, you need to cancel connections, and cleanup your update mechanisms. On app's wake-up you might want to resume the update.

Regarding the view part of the application - use Interface Builder. It might be painful in the beginning, but it pays off in the long run.

View controllers are the glue between model and views. Do not store data in there. Think twice about what to implement where, and who should call it.

This is not related to architecture of the app, but I want to remind that Objective-C is very expressive language. Code should read much like a sentence. Extend classes with protocols. As an example the other day I needed first line of a string. Sure, you can write a one-liner where you find first occurrence of a new-line, and get a substring from beginning till there. But it doesn't look right. I've added - (NSString*)firstLine into my NSString's protocol. Code looks so much better this way, it doesn't need any comments.

There are lots of things to consider in both architecture and design of any project, they both should go hand in hand. If one is causing trouble to the other, you need to adapt. Nothing is written in stone.

iPhone -- renew team provisioning profile

13 votes

In the provisioning portal, the "renew" button for my team provisioning profile is grayed out. And said profile is expired.

How can I renew it?

EDIT: I found the "automatic device provisioning" checkbox and "refresh" button in the organizer in Xcode. But when I select the team profile, check the checkbox, and push the refresh button, I get this message:

An unexpected error occurred. Please try again. If the problem persists, please contact Apple Developer Support (http://developer.apple.com/support).

I suppose I can go to support, but it would still be better to figure out what the problem is without involving them.

I had the same "unexpected error" issue with the Team Provisioning Profile when it expired. I fixed it by deleting it in the Xcode Organizer AND in the ADC Provisioning Portal, then hitting renew in Organizer.

iPhone Icon@2x.png not showing in Retina display

10 votes

For some reason, the iPhone 4 refuses to display my high resolution icon file.

I've checked out these solutions, none of which have worked for me:

http://stackoverflow.com/questions/3389160/how-to-setup-normal-icon-for-iphone3-and-retina-for-iphone-4

http://developer.apple.com/library/ios/#qa/qa2010/qa1686.html

http://appworks.radeeccles.com/programming/cfbundleiconfiles-nice-ready-prime-time/

The icons are in my resources group, and are all named correctly:

  • Icon.png
  • Icon@2x.png
  • Icon-72.png

I've also tried adding them to the Info.plist file, first as an array, then as a dictionary, then simply deleting all icon references from the plist file, but no matter what I do, it still displays the 57x57 icon scaled up.

Can someone who has a working icon setup please post the actual XML incantation required to make this work?

My Solution was simple, but only caught it be painstakingly comparing line-by-line in Apple Docs.

The non-obvious solution that seamed contradictory was "Deleting the Icon file key value". In the previous answer's image, you can see the Icon file still shows "icon.png" and the "Icon files" shows the two: icon.png & icon@2x.png.

I got my app to work by deleting the "Icon file's" key value of "Icon.png" It was the only thing different, in the Apple Docs was the absence of a value for the "Icon file" key. View an image here: Info.plist Apple Docs Image

In addition, I would make sure you are using Apples recommended notation when labeling the photos:

  • 512x512 iTunesArtwork iTunes Image
  • 57x57 Icon.png Home screen for < iPhone 4
  • 114x114 Icon@2x.png Home screen for iPhone 4 High Resolution
  • 72x72 Icon-72.png Home screen for iPad compatibility
  • 29x29 Icon-Small.png Spotlight and Settings
  • 50x50 Icon-Small-50.png Spotlight for iPad compatibility
  • 58x58 Icon-Small@2x.png Spotlight and Settings for iPhone 4 High Resolution

Next Steps...

  1. Clean All targets
  2. Reset Simulator
  3. Relaunch Application
  4. Works fine for iPhone4, reveals large AppIcon = "Icon@2x.png"

Final Steps...

  1. I put the "Icon.png" name back in for the (Icon file) key.
  2. I put this back in to Backwards support iOS 3.0+ so that it still has a value to use.
  3. Clean All Targets again,
  4. Build & Relauch!

This methods seams to clear out any legacy issues and assures that the simulator pulls in the correct files.

Hopes this helps!

P.S. If this helps you solve your problem, be sure to check my comment as the Solution.

Check iOS version at runtime?

9 votes

This is sort of a follow on from my last question. I am using beginAnimations:context: to setup an animation block to animate some UITextLabels. However I noticed in the docs that is says: "Use of this method is discouraged in iOS 4.0 and later. You should use the block-based animation methods instead."

My question is I would love to use animateWithDuration:animations: (available in iOS 4.0 and later) but do not want to exclude folks using iOS 3.0. Is there a way to check to iOS version of a device at runtime so that I can make a decision as to which statement to use?

You must not check iOS version, instead of that you must check in runtime if a particular method is present or not. In your case you can do the following:

if ([[UIView class] respondsToSelector:@selector(animateWithDuration:animations:)]){
// animate using blocks
}
else {
// animate the "old way"
}

OpenFeint with GameCenter really that easy?

9 votes

I was reading this: http://www.openfeint.com/ofdeveloper/index.php/kb/article/000089, and it seemed to make out that the implementation of GameCenter with OpenFeint was as simple as adding one plist to the project (after setting up achievements / leaderboards). But is this really the case? I've just implemented this in my project now and can't see any signs of it working. Nor can I see the app in the GameCenter app.

Could it be because I'm writing a universal iPhone / iPad app? Even though the iPhone app is on iOS 4.1?

Can anyone help me out here??

Thanks

James

Turns out that because the iPad was below 4.0 when I was doing this, GameCenter wouldn't work, even on the iPhone version.

Upgrade to Xcode 3.2.5 (iOS 4.2) and it will work!

How do I flag a method as deprecated in Objective-C 2.0?

9 votes

I'm part of a team developing a fairly large iPad app and there are many different classes we've created as a result. The trouble is some of the methods are now pretty much obsolete and I don't want simply remove them yet as I know some parts of the overall system use the methods... but there are better (newer) variants available which should be used instead (some of the old ones actually call the new ones, but the overall class interface is getting messy).

Is there a way in which I can mark certain methods as depreciated (like @deprecated in Java and [Obsolete] in .NET).

I see that Apple use Availability.h and have tags such as

__OSX_AVAILABLE_BUT_DEPRECATED(__MAC_NA,__MAC_NA,__IPHONE_2_0,__IPHONE_3_0);

... is this the only way to do it (+ is it App Store safe to do this?) or are there alternatives which will flag a warning in XCode?

Source

Deprecation Syntax

Syntax is provided to mark methods as deprecated:

@interface SomeClass
-method __attribute__((deprecated));
@end

or:

#include <AvailabilityMacros.h>
@interface SomeClass
-method DEPRECATED_ATTRIBUTE;  // or some other deployment-target-specific macro
@end

iPhone: Create a reusable component (control) that has some Interface Builder pieces and some code

9 votes

I want to create a reusable component (a custom control) for the iPhone. It consists of several standard controls prearranged on a View, and then some associated code. My goals are:

  1. I want to be able to use Interface Builder to lay out the subviews in my custom control;
  2. I want to somehow package the whole thing up so that I can then fairly easily drag and drop the resulting custom component into other Views, without having to manually rewire a bunch of outlets and so on. (A little manual rewiring is fine, I just don't want to do tons and tons of it.)

Let me be more concrete, and tell you specifically what my control is supposed to do. In my app, I sometimes need to hit a web service to validate data that the user has entered. While waiting for a reply from the web service, I want to display a spinner (an activity indicator). If the web services replies with a success code, I want to display a "success" checkmark. If the web service replies with an error code, I want to display an error icon and an error message.

The single-use way to do this is pretty easy: I just create a UIView that contains a UIActivityIndicatorView, two UIImages (one for the success icon and one for the error icon), and a UILabel for the error message. Here's a screenshot, with the relevant parts marked in red:

alt text

I then wire up the pieces to outlets, and I put some code in my controller.

But how do I package up those pieces -- the code and the little collection of views -- so that I can reuse them? Here are a few things I found that get me partway there, but aren't that great:

  • I can drag the collection of views and controls into the Custom Objects section of the Library; then, later, I can drag them back out onto other views. But (a) it forgets which images were associated with the two UIImages, (b) there is a lot of manual rewiring of four or five outlets, and (c) most importantly, this doesn't do bring along the code. (Perhaps there's an easy way to wire up the code?)
  • I think I could create an IBPlugin; not sure if that would help, and it seems like a lot of work, and also it's not entirely clear to me whether IBPlugins work for iPhone development.
  • I thought, "Hmm, there's code associated with this -- that smells like a controller," so I tried creating a custom controller (e.g. WebServiceValidatorController) with associated XIB file. That actually feels really promising, but then at that point I can't figure out how, in Interface Builder, to drag this component onto other views. The WebServiceValidatorController is a controller, not a view, so I can drag it into a Document Window, but not into a view.

I have a feeling I'm missing something obvious...

I've created similar constructs except that I do not use the result in IB, but instantiate using the code. I'll describe how that works, and at the end I'll give you a hint how that can be used to accomplish what you're after.

I start from an empty XIB file where I add one custom view at the top level. I configure that custom view to be my class. Below in view hierarchy I create and configure subviews as required.

I create all IBOutlets in my custom-view class, and connect them there. In this exercise I ignore the "File's owner" completely.

Now, when I need to create the view (usually in controller as part of while/for-loop to create as much of them as needed), I use NSBundle's functionality like this:

- (void)viewDidLoad
{
    CGRect fooBarViewFrame = CGRectMake(0, 0, self.view.bounds.size.width, FOOBARVIEW_HEIGHT);
    for (MBSomeData *data in self.dataArray) {
        FooBarView *fooBarView = [self loadFooBarViewForData:data];
        fooBarView.frame = fooBarViewFrame;
        [self.view addSubview:fooBarView];

        fooBarViewFrame = CGRectOffset(fooBarViewFrame, 0, FOOBARVIEW_HEIGHT);
    }
}

- (FooBarView*)loadFooBarViewForData:(MBSomeData*)data
{
    NSArray *topLevelObjects = [[NSBundle mainBundle] loadNibNamed:@"FooBarView" owner:self options:nil];
    FooBarView *fooBarView = [topLevelObjects objectAtIndex:0];
    fooBarView.barView.amountInEuro = data.amountInEuro;
    fooBarView.barView.gradientStartColor = data.color1;
    fooBarView.barView.gradientMidColor = data.color2;
    fooBarView.titleLabel.text = data.name;
    fooBarView.titleLabel.textColor = data.nameColor;
    return fooBarView;
}

Notice, how I set owner of nib to self - there's no harm as I didn't connect "File's owner" to anything. The only valuable result from loading this nib is its first element - my view.

If you want to adapt this approach for creating views in IB, it's pretty easy. Implement loading of subview in a main custom view. Set the subview's frame to main view's bounds, so that they are the same size. The main view will become the container for your real custom view, and also an interface for external code - you open only needed properties of its subviews, the rest is encapsulated. Then you just drop custom view in IB, configure it to be your class, and use it as usual.

Differences Between Cocoa and iPhone development

8 votes

I'm currently reading Aaron Hillegass' book "Cocoa Programming for Mac OS X" as it is highly recommended throughout the community. I'm wondering if there's an extreme difference between "Cocoa Programming" and iPhone development. I'm more interested in iPhone development, but I figured iPhone development would be easier to pick up if I was comfortable with Cocoa before moving on.

iPhone programming is a form of Cocoa (technically "Cocoa Touch"). It shares almost all the same programming idioms, and there's a huge overlap in the frameworks.

Hillegass' book is a great starting point for either. After about chapter 7 in Hillegass, you'll start getting into more "Mac" topics like document window management etc. None of this is bad to understand, but that's where it begins to differ in the details, and you'll find that it won't translate quite so directly.

The patterns he teaches you to think in will be useful in all cases. But the actual classes and objects you use for the Mac stuff don't all have equivalences in the iPhone world. On iOS, the view management (UIView) is quite different from Mac's NSView stuff. It's actually simpler and easier to understand on the iPhone, I found.

Hillegass has a new iPhone-specific book out. I haven't browsed through it yet.

What is the difference between GCD Dispatch Sources and select() ?

8 votes

I've been writing some code that replaces some existing:

while(runEventLoop){
  if(select(openSockets, readFDS, writeFDS, errFDS, timeout) > 0){
    // check file descriptors for activity and dispatch events based on same 
  }
} 

socket reading code. I'd like to change this to use a GCD queue, so that I can pop events on to the queue using dispatch_async instead of maintaining a "must be called on next iteration" array. I also am already using a GCD queue to /contain/ this particular action, hence wanting to devolve it to a more natural GCD dispatch form. ( not a while() loop monopolizing a serial queue )

However, when I tried to refactor this into a form that relied on dispatch sources fired from event handlers tied to DISPATCH_SOURCE_TYPE_READ and DISPATCH_SOURCE_TYPE_WRITE on the socket descriptors, the library code that depended on this scheduling stopped working. My first assumption is that I'm misunderstanding the use of DISPATCH_SOURCE_TYPE_READ and DISPATCH_SOURCE_TYPE_WRITE - I had assumed that they would yield roughly the same behavior as calling select() with those socket descriptors.

Do I misunderstand GCD dispatch sources? Or, regarding the refactor, am I using it in a situation where it is not best suited?

The short answer to your question is: none. There are no differences, both GCD dispatch sources and select() do the same thing: they notify the user that a specific kernel event happened or that a particular condition holds true.

Note that, on a mac or iOS device you should not use select(), but rather the more advanced kqueue() and kevent() (or kevent64()).

You may certainly convert the code to use GCD dispatch sources, but you need to be careful not to break other code relying on this. So, this needs a complete inspection of the whole code handling signals, file descriptors, socket and all of the other low level kernel events.

May be a simpler solution could be to maintain the original code, simply adding GCD code in the part that react to events. Here, you dispatch events on different queues depending on the particular type of event.

Blocks instead of performSelector:withObject:afterDelay:

8 votes

I often want to execute some code a few microseconds in the future. Right now, I solve it like this:

- (void)someMethod
{
    // some code
}

And this:

[self performSelector:@selector(someMethod) withObject:nil afterDelay:0.1];

It works, but I have to create a new method every time. Is it possible to use blocks instead of this? Basically I'm looking for a method like:

[self performBlock:^{
    // some code
} afterDelay:0.1];

That would be really useful to me.

There's no built-in way to do that, but it's not too bad to add via a category:

@implementation NSObject (PerformBlockAfterDelay)

- (void)performBlock:(void (^)(void))block 
          afterDelay:(NSTimeInterval)delay 
{
    block = [[block copy] autorelease];
    [self performSelector:@selector(fireBlockAfterDelay:) 
               withObject:block 
               afterDelay:delay];
}

- (void)fireBlockAfterDelay:(void (^)(void))block {
    block();
}

@end

Credit to Mike Ash for the basic implementation.

Good Learning Method for Objective-C?

6 votes

I know this must be asked a millions times and can't be easy to answer as there is o definitive method, but any help would be appreciated, thanks.

I have been playing around with all sorts of things in Xcode and with Objective-C, however I can't seem to find a good way of learning things in an efficient way.

I have bought the book 'Programming in Objective-C 2.0' and its great but just lays down the basics it seems.

I want to learn in the 2D game development direction, then of course 3D after nailing that, if thats the right thing to do?

I am 17 currently in year 13, last year of school/A Levels and am almost definitely taking a gap year. Any good, well known reputable courses online or offline (real world)? This is my first programming language, and I am absolutely serious about learning this.

One last question, is when learning things online, I have in the past started building a feature and learning a certain aspect in programming only to find out after adding more its slows down the app or its to inefficient. Is the key to use a certain method in a certain situation (being os many ways to do the same thing) or use any of those methods and refine it in your app to make it run smoothly? Sorry, its hard for me to know when I have little experience, thus far.

Sorry for rambling on! I would appreciate any help, thank you!

Cocoa and Objective-C Resources helped me a lot. It focuses more on mac programming than iOS.

How-to articles for iPhone development, Objective-C covers the iOS side very well.

Getting current device language in iOS?

6 votes

I'd like to show the current language that the device UI is using. What code would I use?

I want this as an NSString in fully spelled out format. (Not @"en_US")

This will probably give you what you want:

NSLocale *locale = [NSLocale currentLocale];

NSString *language = [locale displayNameForKey:NSLocaleIdentifier 
                                         value:[locale localeIdentifier]];

It will show the name of the language, in the language itself. For example:

Français (France)
English (United States)

How safe is information contained within iPhone app compiled code?

6 votes

I was discussing this with some friends and we began to wonder about this. Could someone gain access to URLs or other values that are contained in the actual objective-c code after they purchase your app?

Our initial feeling was no, but I wondered if anyone out there had definitive knowledge one way or the other?

I do know that .plist files are readily available.

Examples could be things like:

-URL values kept in a string

-API key and secret values

Yes, strings and information are easily extractable from compiled applications using the strings tool (see here), and it's actually even pretty easy to extract class information using class-dump-x (check here).

Just some food for thought.

Edit: one easy, albeit insecure, way of keeping your secret information hidden is obfuscating it, or cutting it up into small pieces.

The following code:

NSString *string = @"Hello, World!";

will produce "Hello, World!" using the strings tool. Writing your code like this:

NSString *string = @"H";
string = [stringByAppendingString:@"el"];
string = [stringByAppendingString:@"lo"];
...

will show the characters typed, but not necessarily in order.

Again: easy to do, but not very secure.

MPMoviePlayer load and play movie saved in app documents

6 votes

I am writing an application that stores the movies in the photo roll into the local documents folder for the app. I can play remote movies using the MPMoviePlayer, however trying to play a movie stored in the documents folder for the app always returns MPMovieLoadStateUnknown.

The notifications are all getting sent and received from the default notification center (MPMoviePlayerLoadStateDidChangeNotification, MPMoviePlayerPlaybackDidFinishNotification). An alert box shows up shortly after getting the loadStateUnknown message in the console, saying that the movie could not be played and the app then receives the movie playback completed notification.

I think that it may be a case that the filename (MPMoviePlayer can only take a URL as the asset location) cannot be found. Has anyone dealt with this issue or similar?

Given that none of the other answers seem to resolve the problem, I'm inclined to think that the problem might be with the Documents file path you are producing.

You should be using the following method to generate the path to the application's documents folder:

NSString *userDocumentsPath = nil;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
if ([paths count] > 0) 
{
     userDocumentsPath = [paths objectAtIndex:0];
}