UIPasteboard returns nil in the background - swift

I am trying to read the Pasteboard for 5 times in the applicatioDidEnterBackground section of the AppDelegate. To print the string I use print(UIPasteboard.general.string!) but it works only into the function and it doesn't in the other nested functions. Let me explain:
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
print(UIPasteboard.general.string!) //here it works perfectly and prints the string correctly
for _ in 0...5 {
print(UIPasteboard.general.string!) //here it returns nil
}
}
I have read other asks similar to the mine but no one of that helped me. I don't know if this is a security restriction, but if you can help me I'll appreciate 🙂

iOS 9 changed UIPasteboard to disallow background access:
iOS 9 UIPasteboard won't work in the background
Apple Developer Forums / App Frameworks / Cocoa Touch
UIPasteboard is not available in background
Presumably they made this change to prevent background apps from spying on your pasteboard contents. Sometimes people use the pasteboard to copy a password from one app to another, so blocking background pasteboard access is a security issue.
Also, some apps (like Facebook) are known to collect as much data about the user as possibly while having much looser privacy policies than Apple's. Blocking background pasteboard access is a way to reduce Facebook's ability to spy on your non-Facebook activities.

Related

Custom URL scheme with custom app behavior

I am making an app that has multiple usage cases. It has the main functionality (activated by pressing the app icon), then other subsets of the main functionality which are activated by a custom URL scheme.
To explain my problem, I should explain how I currently tell my app to behave differently.
I have been using:
-(BOOL)application:didFinishLaunchingWithOptions:
grabbing the url from the options:
[launchOptions objectForKey:[keyArray objectAtIndex:0]]
Now I parse that urlString and grab all of my launchType parameters, putting them in NSUserDefaults. Then I wait for my splash screen to come up, then it will tell my app how to behave.
This seemed okay at first, but then I realized that: if I deep-link into the app, and am presented with functionality B, then the app goes into the background, the next time the app take the foreground (no matter which way), it will display functionality B.
I was wondering if anyone had an idea about the standard practice, what methods do people usually use?
FYI,
I am going to be trying to fix this problem by telling my navigationcontroller to popToRootViewController, when
-(BOOL)application:application handleOpenURL:
is called, UNLESS didFinishLaunchingWithOptions is called before it, in which case, just do what I had previously implemented.
It sounds to me like there are a couple of things for you to consider about this approach.
First of all take a look at the UIApplicationDelegate documentation. -application:willFinishLaunchingWithOptions: warns:
If your app was launched to open a URL, you should examine the value
of the UIApplicationLaunchOptionsURLKey key and return a Boolean value
indicating whether your app can actually open the URL. You should not
try to open the URL in this method. Instead, implement the
application:openURL:sourceApplication:annotation: method in your app
delegate and use that method to open the URL.
Looking at -application:openURL:sourceApplication:annotation: we see:
If your app had to be launched to open the URL, the app calls the
application:willFinishLaunchingWithOptions: and
application:didFinishLaunchingWithOptions: methods first, followed by
this method. The return values of those methods can be used to prevent
this method from being called. (If the application is already running,
only this method is called.)
Secondly it sounds like you are using NSUserDefaults to persistently store what should be a temporary state (if the app was launched via a url or not). Do you ever reset the values you set there or does launching the app via a url once leave it stuck always following that path.
Finally users have a reasonable expectation that apps will resume where they left off. Users will leave your app to respond to phone calls, text messages, notifications, external distractions, needs for other apps, and any number of other reasons. Refusing to allow them to return to where they left off when they resume/relaunch the app (not via a url) may produce a poor user experience.

How to save state of app on application exit

I am working on an iphone game app. I dont want to use core data or nsuserdefaults to store user data. instead i want to keep all activities in memory and then send it to server when user goes back to previous screen, ends game or presses the home button of iphone. Now everything works fine but i am not able to sync user data when user presses home button. I have implemented the appilcationWillTerminate method in my delegate class but its not working out for me as the method is not get called when I press home button of iphone. Can anyone please tell me how to achieve this task?
best regards
What about this method:
Tells the delegate that the application is now in the background.
- (void)applicationDidEnterBackground:(UIApplication *)application
From Apple Docs:
In iOS 4.0 and later, this method is called instead of the applicationWillTerminate: method when the user quits an application that supports background execution. You should use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. You should also disable updates to your application’s user interface and avoid using some types of shared system resources (such as the user’s contacts database). It is also imperative that you avoid using OpenGL ES in the background.
Your implementation of this method has approximately five seconds to perform any tasks and return. If you need additional time to perform any final tasks, you can request additional execution time from the system by calling beginBackgroundTaskWithExpirationHandler:. In practice, you should return from applicationDidEnterBackground: as quickly as possible. If the method does not return before time runs out your application is terminated and purged from memory.
You should use NSUserDefaults to store data about the application state. Then, when the application re-starts, you can load the data from NSUserDefaults to recreate the previous state. However with the new multitasking this is not as necessary as it used to be a couple of years ago.

dumping data to file when app quits

What do you all recommend as the best location in an iphone project to dump data collected from the user to a local file? Would you say that applicationWillTerminate is a good option?
Thanks!
A better option on iOS 4.x is applicationDidEnterBackground:
Indeed, according to Apple docs, an application in the background can be terminated at any time due to low memory conditions. Therefore, the suggestion is making persistent any state information at the moment the app enters background.
An excerpt from the UIApplicationDelegate protocol:
You should use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. You should also disable updates to your application’s user interface and avoid using some types of shared system resources (such as the user’s contacts database). It is also imperative that you avoid using OpenGL ES in the background.
Your implementation of this method has approximately five seconds to perform any tasks and return. If you need additional time...
Also from Apple Docs for applicationWillTerminate:
For applications that do not support background execution or are linked against iOS 3.x or earlier, this method is always called when the user quits the application. For applications that support background execution, this method is generally not called when the user quits the application because the application simply moves to the background in that case. However, this method may be called in situations where the application is running in the background (not suspended) and the system needs to terminate it for some reason.
Therefore if you specifically request to not support backgrounding for your app or you link against iOS 3.x you should consider persisting in both places (applicationWillTerminate and applicationWillEnterBackground) to catch situations as well.

Suspend the application

How can I suspend my application or send a suspend message to my application?
I want to simulate pressing the home button.
There is a private instance method for UIApplication:
The following code would work, (tested in an iPhone 3GS):
UIApplication *app = [UIApplication sharedApplication];
[app performSelector:#selector(suspend)];
In swift:
UIControl().sendAction(#selector(NSURLSessionTask.suspend), to: UIApplication.sharedApplication(), forEvent: nil)
Edit Swift3:
UIControl().sendAction(#selector(URLSessionTask.suspend), to: UIApplication.shared, for: nil)
Quitting your application or sending it to the background programmatically is a violation of the iOS Human Interface Guidelines, which usually doesn't bode well for getting through the review process:
Don’t Quit Programmatically
Never quit an iOS application
programmatically because people tend
to interpret this as a crash. However,
if external circumstances prevent your
application from functioning as
intended, you need to tell your users
about the situation and explain what
they can do about it. Depending on how
severe the application malfunction is,
you have two choices.
Display an attractive screen that describes the problem and suggests a
correction. A screen provides
feedback that reassures users that
there’s nothing wrong with your
application. It puts users in control,
letting them decide whether they want
to take corrective action and continue
using your application or press the
Home button and open a different
application
If only some of your application's features are not working, display
either a screen or an alert when
people activate the feature. Display
the alert only when people try to
access the feature that isn’t
functioning.
The philosophical reason for this is explained earlier in that document:
People, not applications, should
initiate and control actions. Although
an application can suggest a course of
action or warn about dangerous
consequences, it’s usually a mistake
for the app to take decision-making
away from the user. The best apps find
the correct balance between giving
people the capabilities they need
while helping them avoid dangerous
outcomes.
Users feel more in control of an app
when behaviors and controls are
familiar and predictable. And, when
actions are simple and
straightforward, users can easily
understand and remember them.
People expect to have ample
opportunity to cancel an operation
before it begins, and they expect to
get a chance to confirm their
intention to perform a potentially
destructive action. Finally, people
expect to be able to gracefully stop
an operation that’s underway.
There should be no reason that you need to force your application into the background during its operation. It should remain fully functional when displayed onscreen and it should be up to the user when they want to switch away from your application.
You can't do this.
If you want to exit your app, don't fear rejection and love false positive crash report emails from users you could call exit(0);
Use :
sleep(15)
it will suspend your app for specific time
When the application is suspended, a UIApplicationWillResignActiveNotification notification is posted.
I would guess you could try to post this notification manually. Didn't try this myself though.

Can an iPhone app block phone calls?

Is it possible to write an application that will block incoming and outcoming phone calls? Or is the iPhone locked down too much? Thanks!
EDIT: See Rajan Maheshwari's answer below. CallKit now provides this. Even things that seemed they would never change, can change eventually.
Anything that modifies a user's ability to make or receive phone calls is going to run afoul of Apple's basic approach to third-party apps. There are a lot of things that are questionable and you might get away with. Blocking calls is clearly forbidden.
It is now possible to detect and block unwanted phone calls from iOS 10 and above.
See the CallKit framework
The CallKit framework (CallKit.framework) lets VoIP apps integrate with the iPhone UI and give users a great experience. Use this framework to let users view and answer incoming VoIP calls on the lock screen and manage contacts from VoIP calls in the Phone app’s Favorites and Recents views.
CallKit also introduces app extensions that enable call blocking and caller identification. You can create an app extension that can associate a phone number with a name or tell the system when a number should be blocked.
A number of events will potentially interrupt an application - incoming call, SMS message or calendar alert. If the user ignores the interruption your application will continue running. If not, it will terminate.
See Apple docs for more details.
It is possible in iOS 10.
Here's how to do it ->
1.Create a call directory extension
2.Block the incoming call ->
class CustomCallDirectoryProvider: CXCallDirectoryProvider {
override func beginRequest(with context: CXCallDirectoryExtensionContext) {
let blockedPhoneNumbers: [CXCallDirectoryPhoneNumber] = [ phone Numbers here with country code! ]
for phoneNumber in blockedPhoneNumbers.sorted(by: <) {
context.addBlockingEntry(withNextSequentialPhoneNumber: phoneNumber)
}
context.completeRequest()
}
}
Note:
If you are using callKit to receive incoming calls then there is no need to manually block other calls.
Link -> https://developer.apple.com/reference/callkit
An app has not access to the phone feature, and has no way to block a call.
The alternative is to wait for Apple to offer that feature in the future.
In the meantime, you can
Ask your provider - some providers do that
Create a custom ring tone (silent) to be associated to some number (no ring).