To know date and time settings in device from an iPhone application - ios

I want to know whether the user has set their device to automatically set the date and time in the Settings.app in iPhone. I need this information because I want to make user to access some informations in the app only for a day, which he can access again only on second day. But an smart user can change the date and access the information. So I want to check whether they set the date/time automatically for the device or not.
Is there any way for doing so. Please suggest any other alternate way if exist.
Thanks in advance.

I don't believe there exists a way to detect the user's preference regarding the automatic update of the date time settings. To determine the length of time from a given point, you have a few options none of which are absolute or without any error.
Use NSDate, which you already know can be circumvented by manually changing the date on the device.
Use a time server. By querying a time server you can get an independent date time value. Store that value and compare against it to determine if the right amount of time has passed. The drawback of course, is this requires an internet connection to function property.
Use a system clock value or series of values to roughly calculate the time elapsed. A functions like CACurrentMediaTime or mach_absolute_time() can provide a count to compare against. You can take the values and increment them until you have reached a specified duration to reset a flag for your second day check.
None of the options alone will provide an ideal solution, but by combining the approaches, you might achieve an acceptable level of assurance the user is accessing the information only during the time allowed.

This is an alternate suggestion, I had similar problem for a conference app I was developing. I wanted to show some data to user only in the second day of conference.
After discussing getting date option from device with our team. We decided not to use this approach because as you said some user may change date settings and also some user may be reluctantly set their device to other countries time and date zones where there may be date conflict issues for users.
Finally we decided to create a simple web page and get http 200 and http 404 request for that info. You dont have to put your data or whatever to the server, we just wanted to get the response code from web.
So lets say you have a webpage http://xxxxxxxxxxxxxx.pdf or .html we dont put any pdf files to server so user always get http 404 response in that case we disable or hide the related data/button/row whatever. In the second day of conference we put a dummy page so now user can get http 200 response, so we enable button/row/data.
if you decide to use this approach download block for nsurlconnection from here
then use following code:
NSURL *theFileURL=[NSURL URLWithString:#"yoururl"];
NSURLRequest *request = [NSURLRequest requestWithURL:theFileURL];
[URLConnection asyncConnectionWithRequest:request
completionBlock:^(NSData *data, NSURLResponse *response) {
//get data and response
if ([response isKindOfClass:[NSHTTPURLResponse class]])
{
NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse *) response;
//NSString *fileMIMEType = [[httpResponse MIMEType] lowercaseString];
NSLog(#"httpResponse.statusCode %i",httpResponse.statusCode);
if (httpResponse.statusCode==200) {
//correct respond show data
}
else if (httpResponse.statusCode==404)
{
//no file this
NSLog(#"no file at the server");
}
}
//[HUD removeFromSuperview];
} errorBlock:^(NSError *error) {
//get error
NSLog(#"error %#",error);
} uploadPorgressBlock:^(float progress) {
//Upload progress (0..1)
} downloadProgressBlock:^(float progress) {
//Download progress (0.1)
//progress += 0.01;
//HUD.progress = progress;
}];

Related

Best way to check if sharing via SLComposeViewController is successful with a limited (or no) Internet connection

Apple's documentation is clear on using SLComposeViewController to provide sharing capabilites with other social networks such as Twitter and Facebook.
Typical code will use isAvailableForServiceType to verify if a particular service is available and then add a completion handler to the view controller where an SLComposeViewControllerResult can be checked for either SLComposeViewControllerResultCancelled or SLComposeViewControllerResultDone, which check if the user tapped on the 'Post' button or on the 'Cancel' button after the sharing view has been displayed.
The issue here is that if you use SLComposeViewControllerResultDone to validate that the user made the request, you don't actually check if it was successful such as when the user has limited or no connectivity.
I have tried with one of my apps to test this and have noticed that the SLComposeViewControllerResultDone constant is still valid even if airplane mode is turned on such that a request is not possible. What this means is that the user fills out the sharing view fields and taps on 'Post' and my success code executes even though I should really be checking to make sure that the post was indeed successful.
Currently, I figure that the best option is to check for an Internet connection using the standard Reachability options (as recommended here) and disable the sharing button if a connection is not available, but I'm not sure if this is the best solution as it doesn't account for a limited connection where the user can tap on 'Post' but the actual request is unsuccessful.
My question is what is the best method of detecting if a sharing request has successfully completed?
then you need to make sure that you do not write below line in didSelectPost
[self.extensionContext completeRequestReturningItems:nil completionHandler:nil];
and once you get success or fail based on that in the your request handler you can write above line, so your didSelectPost should be like :
- (void)didSelectPost {
NSExtensionItem *inputItem = self.extensionContext.inputItems.firstObject;
NSItemProvider *attachment = inputItem.attachments.firstObject;
if ([attachment hasItemConformingToTypeIdentifier:#"public.url"])
{
//NSString *strLink = [attachement loadItemForTypeIdentifier:#"public.url" options:nil completionHandler:nil];
[attachment loadItemForTypeIdentifier: #"public.url"
options: nil
// make your request here
}];
}
}

How do you "resolve" a GKTurnBasedExchange?

I'm using a GKTurnBasedExchange to send data one way. It's a notification to the other players as certain triggers happen. However, the other players may not even be in the game at that time. The turns have 48 hour timeouts, so in theory if player1 sends said exchange, player3 might not pick it up for a couple of days. That's fine, player 1 doesn't require or expect any response.
But, when player1 tries to save the match data, end the turn or quit the match, I get an error:
Error Domain=GKErrorDomain Code=3 "The requested operation could not
be completed due to an error communicating with the server."
UserInfo=0x19317970 {GKServerStatusCode=5134,
NSUnderlyingError=0x16f15db0 "The operation couldn’t be completed.
status = 5134, Invalid operation for this session because the exchange
was not resolved. All exchanges must be resolved before the current
player can complete this operation.
OK, the bolded text seems pretty self-explanatory except for one little detail: I can't find any reference anywhere to what constitutes a "resolved" exchange. I don't expect a response back to this message. Even if I did, it could take days to receive it. The only option I can see is for the sender to cancel the exchange, which defeats the purpose of sending the exchange in the first place
So, how exactly does one finalize an exchange? What series of steps, besides canceling the exchange, will satisfy game center that the exchange has been "resolved?"
I'm just using:
[theMatch sendExchangeToParticipants:exchangeParticipants
data:exchangeData
localizableMessageKey:#"F1"
arguments:nil
timeout:600
completionHandler:^(GKTurnBasedExchange *exchange, NSError *error)
{
if (error)
{
VLOG(LOWLOG, #"%#", [error description]);
}
}
];
Followed by:
[theMatch saveCurrentTurnWithMatchData:dataCopy completionHandler:^(NSError *error)
{
if (error)
{
VLOG(LOWLOG, #"%#", [error description])
}
}];
The saveCurrentTurnWithMatchData call returns the aforementioned error.
Thanks!
I think I figured this out. Man oh man it's a slog making sense of Apple's documentation.
In the end I didn't make sense of it actually: this is the result of brute force trial and error.
So here's the deal: you can do a lot of things with exchanges, but to actually resolve them you have to call:
saveMergedMatch(matchData: Data, withResolvedExchanges: [GKTurnBasedExchange], completionHandler: ((Error?) -> Void))
There are several catches though.
Only the match's currentParticipant (the player who's turn it is) can call saveMergedMatch successflly.
It will only work for exchanges that are not in .active status.
There are only two ways, as far as I can tell, to programmatically get an exchange out of .active status.
The harder way: all recipients of the exchange have to act on the exchange--itself a murky process, can't help there. If all recipients do respond to it, Game Center itself will handle changing the status of the exchange, I think. Not sure though, because I don't do this. [The only help I can give here is that if you give an exchange a really short timeout when you send it, after the timeout passes Game Center will adjust the exchange's status automatically, and your recipients won't have to do anything.]
The not-much-easier way: the sender and only the sender of the exchange can cancel it, by calling the exchange's method cancel(withLocalizableMessageKey key: String, arguments: [String], completionHandler: ((Error?) -> Void)? = nil). The saving grace of this way is that it doesn't have to be the sender's turn for them to cancel it. This is one of the few times that the current turn-taker doesn't matter. Unfortunately this also has a catch: the exchange can't be cancelled if anyone has already responded to it.
So the upshot is that there is no way for any single player to be guaranteed to be able to resolve an exchange, for two reasons:
The process that moves active exchanges into completed exchanges is only programmatically accessable for the purpose of cancelling the exchange, and only by the player that originated it, and only if no one has responded yet.
The actual process that turns completed exchanges into resolved exchanges can only be triggered by the player in the match's currentParticipant property.
Personally, I can work with this, now that I understand it (I hope) , but without doubt it is quite a pain.
Well, turns out exchanges can't be used. Yet another limitation in Game Kit. For anyone that comes across this thread, I found WWDC 2013 session 506 says:
All participants have to respond for game center to mark the exchange as "completed"
You have to call:
[match saveMergedMatchData:dataCopy
withResolvedExchanges:match.completedExchanges
completionHandler:...];
So, you can't use exchanges for 1-way communications. There has to be a response (or wait for a timeout).
I guess I'll answer to the unasked question of: how to send 1-way communications With notifications.
I think the best API for that is setLocalizableMessageWithKey(key:arguments:) or sendReminderToParticipants(localizableMessageKey:arguments:completionHandler:) on your GKTurnBasedMatch instance.

How to combine multiple notifications of the same kind

I have an iOS app that shows the user a set of different news feeds in a PageViewController. Everytime the app starts, it requests the news data from the backend for every single feed. In case it worked fine, a notification via for every single news feed is sent via NSNotificationCenter so the data can be displayed.
In case of an error, a notification for every single feed is sent as well, triggering a popup message that tells the user something went wrong. But if this happens, a popup will be shown for every news feed, up to the amount of added news feeds.
My question is, how can I combine all those error case notifications to a single one and therefore avoid having many useless and annyoing popups?
if (self.isShowingErrorDialog) {
return; // Or possibly cache to show after current one is dismissed.
} else {
[[UIAlertView ...] show];
self.showingErrorDialog = YES;
}
When you send a notification using NSNotificationCentre, you can include user info. This is basically an NSDictionary with additional information.
Why not just include the timestamp of the failed request. You can test this with some fuzziness to see if you've already put up an alert for this batch of requests.
- (void) notificationListener: (NSNotification*) notification {
static NSDate* lastAlerted = nil;
NSDate* sentDate = notification.userInfo[#"RequestDate"];
if ( lastAlerted != nil && [lastAlerted timeIntervalSince:sentDate] > FUZZY_INTERVAL) {
// post alert
// And update last Alerted
lastAlerted = sentDate;
}
}
The method you need is postNotificationWithName:Object:UserInfo:.
Gordon
I don't think you can.
Just to confirm, the notifications you're sending are Apple remote notifications and the alerts are the system alerts popped up by the message centre.
The alerts occur before you get control, as the user has to have the opportunity to ignore them, or else people would use this as a cheat to make apps run in the background and kill user's batteries.
All you can do is send a batch token in your request, and check on the back end.
Good luck

how to make ruby on rails database api available for a data driven ios app [closed]

It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 10 years ago.
Well , I have just started coding in general. I am trying to make an ios social app with basic picture information taking data from a website ( some what of a flickr-clone)
So , the main website will be built on Ruby on rails.
EDIT :
ok so , i want to know when a person uploads a picture , it will have the following entries:
* name
* who took
* location
I was researching about the gem logtrend (https://github.com/gorsuch/logtrend) , i was wondering if I can make a trending feed of sorts using location?
eg: the user selects a tab which shows them the trending pic ( near them (based on his core location) ?? Can we do something like that ?
I don't know anything about Ruby on Rails but I do know to do what you're trying to do (let user upload photos with their name and GPS location to a server, then allow other users to view that photo by downloading it down to their app).
One way you can build the server is to build a web service with Ruby on Rails.
Web Servcie
The web service (your server) does 2 things:
1) Accept a Request
2) Return a Response
With the web service, you accept HTTP POST or GET request, then your server's logic code will parse the "parameters" or "variables" inside the POST or GET.
Once your server has these variables, it can save them to the database (an ORM would really make it easier).
Your web service can then return a response using HTTP Status Code or a JSON formatted response.
Example Scenario
1) iPhone app takes photo and then makes a HTTP POST request to your Ruby server using ASIHttpRequest or AFNetworking.
// ASIExample
-(void)uploadPhotoToServer
{
NSURL *url = [NSURL urlWithString:myUploadWebServiceURL];
__block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url];
// ---------------------------------------------------------------
// setting the POST parameters below
// note: you will need to get the NSData from a UIImage object
// ---------------------------------------------------------------
[request setData:imageData withFileName:#"myphoto.jpg" andContentType:#"image/jpeg" forKey:#"photo"];
[request setPostValue:fldName.text forKey:#"name"];
[request setPostValue:[NSNumber numberWithDouble:myLatitude] forKey:#"latitude"];
[request setPostValue:[NSNumber numberWithDouble:myLongitude] forKey:#"longitude"];
[request setCompletionBlock:^{
int statusCode = [request responseStatusCode];
if(statusCode == 200)
{
[self alertUploadComplete];
}
}];
[request setFailBlock:^{
NSLog(#"Server error: %#", [[request error] localizedDescription]);
[self alertConnectionProblem];
}];
[request startAsynchronous];
}
2) Server receives the request, parses the data and returns a response
// Symfony Web Framework example (PHP based web framework)
public function uploadPhotoAction()
{
// --------------------------------------------------
// check to make sure all POST parameters are sent
// in the POST request by iPhone app.
// --------------------------------------------------
if(
!isset($_REQUEST['name']
|| !isset($_REQUEST['latitude']
|| !isset($_REQUEST['longitude']
|| !isset($_REQUEST['photo']
)
{
return new Response($this->sendResponse(406, 'Missing POST parameters');
}
else // assumes safe to continue
{
/*
write code to save the your name, latitude, longitude to your database here
*/
/*
save your photo to your server's dedicated photo folder, then store
the file path to the file in your database entry in the above step
*/
return new Response($this->sendResponse(200, 'Photo uploaded'));
}
}
A couple of gems that you could make use of are Devise coupled with OmniAuth for social logins/authentication.
For more gems by categories, check out Ruby Toolbox.
Hope you the best of luck!
Is this achievable through ruby on rails ?
Yes, yes it is.
what gems should I be using ?
Depends upon your approach and featureset.
Also , which gems can be used to make API's to feed the IOS app ?
I think you're misunderstanding what an API is. The API is HOW the client will interact with the host.
I would suggest you investigate using JSON to communicate between your IOS app and your Web app. Both IOS and Ruby/Rails are very capable of supporting JSON and it is relatively lightweight.
Also, you need to define, in detail, what the IOS application is going to do where it needs interaction with the Web app.
Example
IOS App (IA) will save a picture to the Web App (WA).
IA may save the same picture to WA (overwriting)
IA will be told if WA is full
IA will log into WA
IA can log out from WA
IA can change password on WA
WA will reject commands from a non-logged in IA
IA can retrieve user's pictures from WA
IA can retrieve any other user's pictures from WA
etc.
Now, for each one, you design the API to support that function.

How to tell if TWRequest performRequestWithHandler failed or succeeded

I am posting a request and checking for errors like so:
// Send request out on a background thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if ([urlResponse statusCode] == 200) {
NSLog(#"Tweet Successful");
}else {
NSLog(#"Tweet Failed");
if (responseData) {
// Use the NSJSONSerialization class to parse the returned JSON
NSError *jsonError;
NSArray *requestResponse =
[NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableLeaves
error:&jsonError];
if (requestResponse) {
NSLog(#"%#",requestResponse);
} else {
NSLog(#"%#",jsonError);
}
}
}
}];
});
It seems to work fine, so far as the request is concerned. My intention was to queue the request on failure and try again at a later date, or not depending on the error and how many attempts had failed thus far.
The problem I have is that I find it frequently appears to fail, with error 34 "Page not Found" where in fact the request did succeed, was posted as intended and can be seen clear as day in twitter stream.
Now, if I can't trust the error code returned then I can't really go on and keep retrying. How do I know for sure if it succeeds or fails?
RECENT OBSERVATIONS:
Recently, I tried to post a photo from Apple photo app directly and it sent me an alert that read "Tweet may not have been successful". That is funny, because that is basically what I was coming to as my only option in this case. This makes me think that even Apple had to acknowledge that there is not way to tell for sure that post failed when the return does not confirm it.
according to every example found in researching this problem, none of which use any other API than what you are using, and including this example from twitter's own documentation for posting a photo to the API, none of them check the urlResponse code first.
the most that ever seems to be done is this example from twitter's documentation where a GET is performed and then the response is processed. notice that it checks the responseData first, and if it exists, it is simply treated like success. only if there is no responseData is there an attempt to bother looking at the error. the example does not bother with the urlResponse … and neither does any other example i saw in 10 minutes of googling.
(finally, i doubt this matters, or it may be because you cleaned up the example for the display, but you're processing the error on the main-queue when you are not performing any UI. you could do the processing in the handler immediately, and pass along whatever post-processing you do to whatever UI you are trying to display it with. i doubt post-processing the response in the main-queue as opposed to the queue of the handler (as shown in both examples cited here and all other examples i've seen) is really causing a problem, but i wonder if it might cut down on the incidence of false negatives you are seeing. at the very least, it will make your response and any UI display of the response cleaner and more efficient.)

Resources