问题
Is it possible to force the user to upgrade once there is a new version of my application available in the iTunes Store?
I am presently working on an application. However, I want to force the upgrade whenever I upload a newer version, because the upgrade will have more features and I want to discard the previous version. Is this possible by default with iPhone or do I have to write my own implementation to check the current version and compare it to the store?
回答1:
The only way system handles updates of your application is prompting user that update is available in standard AppStore application.
Also, standalone application is not aware of available updates so you'll need to implement your web service where application can check if the current version is valid.
And I'm not sure if this conforms with Apple rules on applications, like (can't find proof-link though) you cannot upload trial versions for an application.
* EDIT * This answer is no longer true. See other upvoted answers for current truth.
回答2:
I have done this feature by getting version from itunes webservice and comparing with the current version.. Following is my code
NSString *version = @"";
NSURL *url = [NSURL URLWithString:@"http://itunes.apple.com/lookup?id=<Your app ID>"];
versionRequest = [ASIFormDataRequest requestWithURL:url];
[versionRequest setRequestMethod:@"GET"];
[versionRequest setDelegate:self];
[versionRequest setTimeOutSeconds:150];
[versionRequest addRequestHeader:@"Content-Type" value:@"application/json"];
[versionRequest startSynchronous];
//Response string of our REST call
NSString* jsonResponseString = [versionRequest responseString];
NSDictionary *loginAuthenticationResponse = [jsonResponseString objectFromJSONString];
NSArray *configData = [loginAuthenticationResponse valueForKey:@"results"];
for (id config in configData)
{
version = [config valueForKey:@"version"];
}
//Check your version with the version in app store
if (![version isEqualToString:[itsUserDefaults objectForKey:@"version"]])
{
ProAlertView *createUserResponseAlert = [[ProAlertView alloc] initWithTitle:@"New Version!!" message: @"A new version of app is available to download" delegate:self cancelButtonTitle:@"Cancel" otherButtonTitles: @"Download", nil];
[createUserResponseAlert show];
[createUserResponseAlert release];
}
And put the app id in the itunes link see the code below..
- (void)alertView:(UIAlertView *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
// the user clicked one of the OK/Cancel buttons
if (buttonIndex == 1)
{
NSString *iTunesLink = @"itms-apps://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftwareUpdate?id=<appid>&mt=8";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:iTunesLink]];
}
}
Note : You need JSONKit frame work and ASIHttp frame work to make the webservice calls..
回答3:
You can detect if the app needs an update then take some custom action like alert the user an update is available. Here is a code snippet that detects that an update is available.
-(BOOL) needsUpdate{
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString* appID = infoDictionary[@"CFBundleIdentifier"];
NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@", appID]];
NSData* data = [NSData dataWithContentsOfURL:url];
NSDictionary* lookup = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if ([lookup[@"resultCount"] integerValue] == 1){
NSString* appStoreVersion = lookup[@"results"][0][@"version"];
NSString* currentVersion = infoDictionary[@"CFBundleShortVersionString"];
if (![appStoreVersion isEqualToString:currentVersion]){
NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
return YES;
}
}
return NO;
}
回答4:
If you absolutely have to, you can launch the App Store so that your users can get the latest version from there. I would recommend making this optional, or at least presenting a dialogue first.
// iTunesLink should be your applications link
NSString *iTunesLink = @"http://phobos.apple.com/WebObjects/MZStore.woa/wa/viewSoftware?id=284417350&mt=8";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:iTunesLink]];
回答5:
This question was originally posted 7 years ago, and while some of the answers remain relevant, here is a more up-to-date approach.
I recommend https://github.com/ArtSabintsev/Siren which is Swift 3 compatible and can be installed with Cocoapods or Carthage.
CocoaPods, Swift 3 support:
pod 'Siren'
Carthage:
github "ArtSabintsev/Siren"
回答6:
A system for forced upgrades should be part of every application that has a dependance on something external to that application. Both Apple and Google claim that if an app uses something external then that external API should live forever, never change, etc., etc., but that's simply unrealistic. And if that's the case, if the services that the app depends on can change then there MUST be a way for the app to check and see if it should restrict functionality and prompt the user to get the latest version or things will simply mysteriously fail.
This could and should be something that Apple and Google provide, but they don't so every app outside of a few games needs to build this, SO...
I've started a rails based open-source (Apache 2.0) project to create a solution to this problem. It's called Application-[Ctrl], and it's very much a work in progress, but you are welcome to use it and I welcome contributions of any kind. If I can get this up and running in my spare time I'll provide this to all app developers with some very reasonable level of free service and of course every company will always be able to spin up it's own deployment.
It's here on GitHub: https://github.com/SlalomDigital/ApplicationCtrl
Contribute and help me solve this problem for good!
回答7:
There's no automated way to do it, you would have to write something manually.
回答8:
Your business/design plan should never contain the phrase "force the user". People get angry when you make them do something. Imagine a user in a hurry who opens your nifty little app one morning only to discover you are forcing him to upgrade before he can use the app for what he needs. Imagine he's stuck out in the wilds having to use Edge to download. He won't be happy.
If you follow this plan long enough, one of your upgrades will inevitably introduce a noticeable bug. If you force users to use a buggy version they will rebel.
I have been conditioned by experience to cringe whenever I see "more features" used to describe a new version of software because this inevitably means feature bloat. Designers tend to keep grafting more and more features onto apps until one app does everything. This is particularly dangerous on a platform like the iPhone where making one app do to many things rapidly overwhelms the interface and the responsiveness of the app.
Edit01: My comment here How to Update an Application After Users Pay For Upgrade might also be relevant to your plans. If your upgrade design cuts Apple out of the revenue loop, its a non-starter.
Update:
Just to clarify based on a comment below: Yes, sometimes you do have to require users to upgrade. However, that is much different from designing the app from the start to force users to upgrade every time the developer releases a new version.
Such a design is intended to make the developer's life easy and not the user's. Every time a user has to spend time upgrading for a benefit they did not ask for and perhaps do not want, you've taken time and resources from the customer. Design that offload time and effort from the developer to the user are bad designs because people ultimately buy software for their own benefit. When you decrease that benefit, you decrease the softwares ultimate profitability.
So, no designer should design software that forces the users to do something the user does not wish to unless it is an absolute technical necessity. This is of course a rule of thumb but it is a very good one.
回答9:
My app update to the App store was just rejected exactly for this reason. We added a feature to check the installed version against the current release and if it's not a supported version, we force them to update.
Apple rejected this.
So back to the design board!
回答10:
The other answers indicate that one has to implement the forced updating functionality oneself. It's a shame really, I wish it wasn't so. My very first update to an iOS Application is to be released tomorrow, and fortunately it won't be problem, as we have only made changes to the app. However when we will eventually change the structure of our webservices, it would be really useful to be able to force updates, so that our server doesn't have to support each and every app version.
There is an alternative to forced updates however, which seems to be unmentioned in this thread. You could have every webservice call that produces data attach a schema to the data, which tells the app how that data should be deserialised in your app. This enables you to change the structure of data produced by get-requests without breaking deserialisation in the app. Of course this assumes that the interpreter that you write, will not itself change, but that is a somewhat reasonable assumption to make when it has matured.
Post requests could be "schema-fied" through interaction. With this I mean that before every post-request you make, you ask for instructions on how to call the up to date webservice. You process the instructions using an attached schema for that, and then you make the actual call to the webservice. Essentially this means that every post request requires 2 requests, but that can be okay.
However, no matter if you implement forced updating or schema interpretation the functionality has to be present in the app from day 1 when it hits the App Store. Otherwise you're in the same mess. All of this complexity would be unnecessary if Apple implemented forced updating for us developers. Schema interpretation would still be a usability improvement if forced updating existed though. But it bugs me a little that Apple doesn't have forced updating, because at least with it, one could introduce one's own anti-break updating measures after the app was released.
回答11:
Hello for anyone in the future I found this tutorial which should help anyone, it helped me.
http://codewithchris.com/tutorial-how-to-implement-in-app-update-functionality-in-your-iphoneipad-app/
Edit (your code will look something similar to what's below):
// Try to get version
NSString *versionNumber = [[[NSBundle mainBundle] infoDictionary] objectForKey:@"CFBundleVersion"];
NSURL *updateUrl = [NSURL URLWithString:@"http://yourdomain.com/yourupdatefile.xml"];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:updateUrl
cachePolicy:NSURLCacheStorageNotAllowed
timeoutInterval:20.0];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:urlRequest
returningResponse:&response
error:&error];
// Check no error, then parse data
if (error == nil)
{
// Parse response into a dictionary
NSPropertyListFormat format;
NSString *errorStr = nil;
NSDictionary *dictionary = [NSPropertyListSerialization propertyListFromData:data
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&errorStr];
if (errorStr == nil)
{
@try {
// Try to see if the current app version exists in the update xml
NSString *itunesUrl = [dictionary objectForKey:versionNumber];
if (itunesUrl)
{
// Show dialog to ask user to update!
}
else {
// Version not in XML
}
} @catch (NSException *e) {
// Error with retrieving the key
}
}
else {
// Error with parsing data into dictionary
}
}
However, upon further research i've found this to be a great solution for if you aren't using a server.
-(BOOL) needsUpdate{
NSDictionary* infoDictionary = [[NSBundle mainBundle] infoDictionary];
NSString* appID = infoDictionary[@"CFBundleIdentifier"];
NSURL* url = [NSURL URLWithString:[NSString stringWithFormat:@"http://itunes.apple.com/lookup?bundleId=%@", appID]];
NSData* data = [NSData dataWithContentsOfURL:url];
NSDictionary* lookup = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
if ([lookup[@"resultCount"] integerValue] == 1){
NSString* appStoreVersion = lookup[@"results"][0][@"version"];
NSString* currentVersion = infoDictionary[@"CFBundleShortVersionString"];
if (![appStoreVersion isEqualToString:currentVersion]){
NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
return YES;
}
}
return NO;
}
In the:
if (![appStoreVersion isEqualToString:currentVersion]){
NSLog(@"Need to update [%@ != %@]", appStoreVersion, currentVersion);
return YES;
}
Portion of the code you set what you want to do if it's not equal, this is where you send the user to the app store to download the latest version.
回答12:
You can use below url to get the information of any app You just know your Apple ID of your app.
You can get this Apple ID in the itunesconnect.com
>your app>app information page
GET: http://itunes.apple.com/lookup?id=
回答13:
Of course there is no way. The user should make the decision if he wants to download a newer version of your application or not.
The AppStore will display if there arenew versions, so I also do not think that Apple will allow this. Also I do not know how you would do this? You could check it via an internet connection, but that's not the way Apple likes and so you won't have a chance to do this.
来源:https://stackoverflow.com/questions/2221436/can-i-force-an-iphone-user-to-upgrade-an-application