Id like to be able to track if the user shared by facebook, twitter, etc, but it seems there's no way to know which method was selected. Is there?
You can use Activity Types in setCompletionHandler
UIActivityViewController *activityVC = [[UIActivityViewController alloc]initWithActivityItems:activityItems applicationActivities:nil];
[activityVC setCompletionHandler:^(NSString *activityType, BOOL completed) {
if([activityType isEqualToString: UIActivityTypeMail]){
NSLog(#"Mail");
}
if([activityType isEqualToString: UIActivityTypePostToFacebook]){
NSLog(#"Facebook");
}
}];
[self presentViewController:activityVC animated:TRUE completion:nil];
Built-in activity types for which the system has built-in support for.
NSString *const UIActivityTypePostToFacebook;
NSString *const UIActivityTypePostToTwitter;
NSString *const UIActivityTypePostToWeibo;
NSString *const UIActivityTypeMessage;
NSString *const UIActivityTypeMail;
NSString *const UIActivityTypePrint;
NSString *const UIActivityTypeCopyToPasteboard;
NSString *const UIActivityTypeAssignToContact;
NSString *const UIActivityTypeSaveToCameraRoll;
Edited for iOS 8
Please note that this will generate a compiler warning in iOS 8, you need to use the setCompletionWithItemsHandler method instead of the setCompletionHandler method.
Replace:
[activityVC setCompletionHandler:^(NSString *activityType, BOOL completed) {
with:
[activityVC setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
In Swift 4:
activityViewController.completionWithItemsHandler = { activity, success, items, error in
if !success{
print("cancelled")
return
}
if activity == .postToTwitter {
print("twitter")
}
if activity == .mail {
print("mail")
}
}
swift 3
let activityViewController:UIActivityViewController = UIActivityViewController(activityItems: [screenCapture], applicationActivities: nil)
activityViewController.excludedActivityTypes = [UIActivityType.print, UIActivityType.postToWeibo, UIActivityType.copyToPasteboard, UIActivityType.addToReadingList, UIActivityType.postToVimeo]
activityViewController.completionWithItemsHandler = { activity, success, items, error in
if !success{
print("cancelled")
return
}
if activity == UIActivityType.postToFacebook {
print("facebook")
}
if activity == UIActivityType.mail {
print("mail")
}
}
self.present(activityViewController, animated: true, completion: nil)
You can use this lib https://github.com/rdougan/RDActivityViewController to identify which activity has been touched and return custom data by activity just by implementing its protocol.
Like This:
- (NSArray *)activityViewController:(NSArray *)activityViewController itemsForActivityType:(NSString *)activityType
{
if ([activityType isEqualToString:UIActivityTypePostToTwitter]) {
return #[#"Twitter text"];
} else if ([activityType isEqualToString:UIActivityTypeMessage]) {
return #[#"Message text"];
} else if ([activityType isEqualToString:UIActivityTypeMail]) {
return #[#"Mail text"];
} else if ([activityType isEqualToString:UIActivityTypePostToFacebook]) {
return #[#"Facebook text"];
} else {
return #[#"Default text"];
}
}
I hope I have helped you!
Related
I can't get my drag and drop with DataRepresentation to work with Transferable. I'm trying to drag and drop instances of DataSettings which is an NSManagedObject that conforms to NSSecureCoding.
Here's my UTType:
extension UTType {
static var encoderSettings = UTType(exportedAs: "com.simulator.EncoderSettings")
}
Here's my conformance to Transferable:
extension DataSettings: Transferable {
var data: Data? {
try? NSKeyedArchiver.archivedData(withRootObject: self, requiringSecureCoding: true)
}
public static var transferRepresentation: some TransferRepresentation {
/*DataRepresentation(contentType: .commaSeparatedText) { setting in
let data = setting.data
print("DataRepresentation: \(data)")
return data!
} importing: { data in
print("data: \(data)")
return DataSettings()
}*/
DataRepresentation(contentType: .encoderSettings) { setting in
let data = setting.data
print("DataRepresentation: \(data)")
return data!
} importing: { data in
print("data: \(data)")
return DataSettings()
}
// ProxyRepresentation(exporting: \.title)
}
}
Here's a view where I'm testing my drop destination:
struct DropTest: View {
#State var isDropTargeted = false
var body: some View {
Color.pink
.frame(width: 200, height: 200)
.dropDestination(for: EncoderSettings.self) { setting, location in
print("\(setting)")
return true
} isTargeted: {
isDropTargeted = $0
print("Got it!!!")
}
}
}
Here's my Info plist:
The ProxyRepresentation (String) works but I need the actual Data.
The dragging starts (i.e.: I can drag the view that has the .draggable with DataSettings) but I can't drop it on my DropTest view. I can drop it on a view or app that accepts the ProxyRepresentation.
What am I missing?
I am trying Vision kit for iOS 11. I can use Vision and I can find boundbox values face. But I don't know how can I draw a rectangle using this points. I hope so my question is clear.
Hope you were able to use VNDetectFaceRectanglesRequest and able to detect faces. To show rectangle boxes there are lots of ways to achieve it. But simplest one would be using CAShapeLayer to draw layer on top your image for each face you detected.
Consider you have VNDetectFaceRectanglesRequest like below
let request = VNDetectFaceRectanglesRequest { [unowned self] request, error in
if let error = error {
// somthing is not working as expected
}
else {
// we got some face detected
self.handleFaces(with: request)
}
}
let handler = VNImageRequestHandler(ciImage: ciImage, options: [:])
do {
try handler.perform([request])
}
catch {
// catch exception if any
}
You can implement a simple method called handleFace for each face detected and use VNFaceObservation property to draw a CAShapeLayer.
func handleFaces(with request: VNRequest) {
imageView.layer.sublayers?.forEach { layer in
layer.removeFromSuperlayer()
}
guard let observations = request.results as? [VNFaceObservation] else {
return
}
observations.forEach { observation in
let boundingBox = observation.boundingBox
let size = CGSize(width: boundingBox.width * imageView.bounds.width,
height: boundingBox.height * imageView.bounds.height)
let origin = CGPoint(x: boundingBox.minX * imageView.bounds.width,
y: (1 - observation.boundingBox.minY) * imageView.bounds.height - size.height)
let layer = CAShapeLayer()
layer.frame = CGRect(origin: origin, size: size)
layer.borderColor = UIColor.red.cgColor
layer.borderWidth = 2
imageView.layer.addSublayer(layer)
}
}
More info can be found here in Github repo iOS-11-by-Examples
Here is easy and simple way to draw boxes.
let faceRequest = VNDetectFaceRectanglesRequest(completionHandler:self.faceDetection)
func faceDetection (request: VNRequest, error: Error?) {
guard let observations = request.results as? [VNFaceObservation]
else { print("unexpected result type from VNFaceObservation")
return }
guard observations.first != nil else {
return
}
// Show the pre-processed image
DispatchQueue.main.async {
self.resultImageView.subviews.forEach({ (subview) in
subview.removeFromSuperview()
})
for face in observations
{
let view = self.CreateBoxView(withColor: UIColor.red)
view.frame = self.transformRect(fromRect: face.boundingBox, toViewRect: self.analyzedImageView)
self.analyzedImageView.image = self.originalImageView.image
self.resultImageView.addSubview(view)
}
}
}
//MARK - Instance Methods
func boxView(withColor : UIColor) -> UIView {
let view = UIView()
view.layer.borderColor = withColor.cgColor
view.layer.borderWidth = 2.0
view.backgroundColor = UIColor.clear
return view
}
//Convert Vision Frame to UIKit Frame
func transformRect(fromRect: CGRect , toViewRect :UIView) -> CGRect {
var toRect = CGRect()
toRect.size.width = fromRect.size.width * toViewRect.frame.size.width
toRect.size.height = fromRect.size.height * toViewRect.frame.size.height
toRect.origin.y = (toViewRect.frame.height) - (toViewRect.frame.height * fromRect.origin.y )
toRect.origin.y = toRect.origin.y - toRect.size.height
toRect.origin.x = fromRect.origin.x * toViewRect.frame.size.width
return toRect
}
I momently developing a application with a tab bar and some navigation view controllers in Storyboard using iOS 6 and Xcode 4.5
Usually the app should support all interface orientations but I have two views that only should support portrait mode.
So I added the following code to the view controllers:
-(BOOL)shouldAutorotate
{
return NO;
}
-(NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationPortrait;
}
On a other app I developed without storyboard and navigation view controller on iOS 6 it works but her NOT! :/
I hope someone can help, because I found some other post that where not helpful...
With best regards from Germany
Laurenz
EDIT:
I also tried - Doesn't work! :
- (NSUInteger)supportedInterfaceOrientations
{
return UIInterfaceOrientationMaskPortrait;
}
As far as I can tell, this problem arises because the UITabBarController and UINavigationController are returning their own default values for -(BOOL)shouldAutorotate and -(NSUInteger)supportedInterfaceOrientations.
One solution is to extend both of those classes via categories (or just subclass), in order to return the appropriate values from your own implementations of these methods in your view controller. This is what worked for me (you can just drop this into your App Delegate):
#implementation UITabBarController(AutorotationFromSelectedView)
- (BOOL)shouldAutorotate {
if (self.selectedViewController) {
return [self.selectedViewController shouldAutorotate];
} else {
return YES;
}
}
- (NSUInteger)supportedInterfaceOrientations {
if (self.selectedViewController) {
return [self.selectedViewController supportedInterfaceOrientations];
} else {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
#end
#implementation UINavigationController(AutorotationFromVisibleView)
- (BOOL)shouldAutorotate {
if (self.visibleViewController) {
return [self.visibleViewController shouldAutorotate];
} else {
return YES;
}
}
- (NSUInteger)supportedInterfaceOrientations {
if (self.visibleViewController) {
return [self.visibleViewController supportedInterfaceOrientations];
} else {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
#end
By default, all your view controllers will continue to autorotate. In the two View Controllers that should only support portrait mode, implement the following:
-(BOOL)shouldAutorotate {
return NO;
}
-(NSUInteger)supportedInterfaceOrientations {
return UIInterfaceOrientationMaskPortrait;
}
Excellent answer by Jonathan.
I modified his code little bit to handle navigation controller in a single snippet.
- (BOOL)shouldAutorotate {
if (self.selectedViewController) {
if ([self.selectedViewController isKindOfClass:[UINavigationController class]]) {
return [[[(UINavigationController*)self.selectedViewController viewControllers] lastObject] shouldAutorotate];
}
return [self.selectedViewController shouldAutorotate];
} else {
return YES;
}
}
- (NSUInteger)supportedInterfaceOrientations {
if (self.selectedViewController) {
if ([self.selectedViewController isKindOfClass:[UINavigationController class]]) {
return [[[(UINavigationController*)self.selectedViewController viewControllers] lastObject] supportedInterfaceOrientations];
}
return [self.selectedViewController supportedInterfaceOrientations];
} else {
return UIInterfaceOrientationMaskAllButUpsideDown;
}
}
Hi, I have already uploaded a sqlite3 file to icloud. Now I want to download this file to my APP's Document folder. After I pressed the download button, it will show the success information. But in fact, there is no sqlite file in the documents folder or maybe the file is broken. Could someone help me?
-(IBAction)downloadPressed:(id)sender
{
if(![self downloadFileIfNotAvailable:self.icloudURL])
{
[self displayAlert:#"Warning!!" withmessage:#"failed to restore"];
}else{
[self displayAlert:#"Congratulations" withmessage:#"restore sccuessfully"];
}
}
-(BOOL)downloadFileIfNotAvailable:(NSURL *)file
{
NSNumber* isIniCloud = nil;
NSError* err;
if ([file getResourceValue:&isIniCloud forKey:NSURLIsUbiquitousItemKey error:nil]) {
// If the item is in iCloud, see if it is downloaded.
if ([isIniCloud boolValue]) {
NSFileManager* fm = [NSFileManager defaultManager];
if([fm removeItemAtPath:self.filePath error:&err])
{
if (![fm startDownloadingUbiquitousItemAtURL:file error:nil]) {
return NO;
}else{
return YES;
}
}
}
return NO;
}
return NO;
}
I've to integrated the FB SDK 3.1 in my ios application.
I successfully share an image on my wall, but i'm not able to set the "via [appname]" (it takes by default "via ios"). I've already put in my info.plist file the appid value.
I'm also not able to make the sharing work for ios5 (it replies with Error 400).
Following there's the code i use:
- (void)viewDidLoad{
appDelegate = [[UIApplication sharedApplication]delegate];
if (!appDelegate.session.isOpen) {
appDelegate.session = [[FBSession alloc] init];
if (appDelegate.session.state == FBSessionStateCreatedTokenLoaded) {
[appDelegate.session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
}];
}
}
and when i have to share, i call this method:
- (IBAction)fbShare:(id)sender {
if (appDelegate.session.isOpen) {
BOOL displayedNativeDialog = [FBNativeDialogs presentShareDialogModallyFrom:self
initialText:textView.text
image:img
url:nil
handler:nil];
if (!displayedNativeDialog) {
[self performPublishAction:^{
[FBRequestConnection startForUploadPhoto:img
completionHandler:^(FBRequestConnection *connection, id result, NSError *error) {
}];
}];}
} else {
if (appDelegate.session.state != FBSessionStateCreated) {
appDelegate.session = [[FBSession alloc] init];
}
[appDelegate.session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
}];}
}
- (void) performPublishAction:(void (^)(void)) action {
if ([FBSession.activeSession.permissions indexOfObject:#"publish_actions"] == NSNotFound) {
[FBSession.activeSession reauthorizeWithPublishPermissions:[NSArray arrayWithObject:#"publish_actions"]
defaultAudience:FBSessionDefaultAudienceFriends
completionHandler:^(FBSession *session, NSError *error) {
if (!error) {
action();
}
else{
}
}];
} else {
action();
}}
Any hint?
Thanks a lot,
erica
I successfully share an image on my wall, but i'm not able to set the "via [appname]" (it takes by default "via ios"). I've already put in my info.plist file the appid value.
Most likely you've not set the Facebook app name. I'd recommend looking it at https://developers.facebook.com/apps admin panel