UIActivityViewController to share images to WeChat not work - ios

When I use Apple's UIActivityViewController to share a few images to WeChat (weixin). I find that sometimes it doesn't work. Most of the time it works well when I select only 1~3 images, but if I share 9 images (largest number allowed by WeChat), it will certainly fail, and the console will print
2016-04-01 16:14:34.258 EverPhoto[5567:1981394] plugin
com.tencent.xin.sharetimeline interrupted 2016-04-01 16:14:34.258
EverPhoto[5567:1981394] plugin com.tencent.xin.sharetimeline
invalidated
Here is the code:
__weak typeof(self) __weakSelf = self;
self.activityViewController = [[UIActivityViewController alloc] initWithActivityItems:self.shareItems applicationActivities:nil];
self.activityViewController.excludedActivityTypes = #[UIActivityTypePostToFacebook,
UIActivityTypePostToTwitter,
UIActivityTypePostToVimeo,
UIActivityTypePostToTencentWeibo,
UIActivityTypePrint,
UIActivityTypeCopyToPasteboard,
UIActivityTypeAssignToContact,
UIActivityTypeSaveToCameraRoll,
UIActivityTypeAddToReadingList,
UIActivityTypePostToFlickr,
];
self.activityViewController.completionWithItemsHandler = ^(NSString * __nullable activityType, BOOL completed, NSArray * __nullable returnedItems, NSError * __nullable activityError){
DLog(#"shareCompleted : %#", completed ? #"YES" : #"NO")
__weakSelf.shareItems = nil;
__weakSelf.activityViewController = nil;
};
[self.containerVc presentViewController:self.activityViewController animated:YES completion:nil];
ShareItems is the custom object that implemented the protocol UIActivityItemSource.
P.S. I tried APP Google Photo and found it has done very well in its share function. It can share 9 images with even original HD size of system photo asserts to WeChat using UIActivityViewController.
So, how should I solve this problem?

WeChat's Share Extension is Terminated due to App Extension's Memory Limit.
According to Apple's App Extension Programming Guide: Optimize Efficiency and Performance
Memory limits for running app extensions are significantly lower than the memory limits imposed on a foreground app. On both platforms, the system may aggressively terminate extensions because users want to return to their main goal in the host app. Some extensions may have lower memory limits than others: For example, widgets must be especially efficient because users are likely to have several widgets open at the same time.
1.I created 9 very small images,and shared with WeChat successfully:
- (UIImage *)imageWithColor:(UIColor *)color
{
CGRect rect = CGRectMake(0, 0, 1, 1);
UIGraphicsBeginImageContext(rect.size);
CGContextRef context = UIGraphicsGetCurrentContext();
CGContextSetFillColorWithColor(context, [color CGColor]);
CGContextFillRect(context, rect);
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
2.You can scale down your images before sharing them with WeChat,here is some Scale methods

I have the same problem.#wj2061's answer is right but not the solution. I think you probably set shareItem with UIImage. If you have the image's fileUrl, set it to shareItem. If not, try save the UIImage to file first.
in your shareItem class, return the fileUrl.
- (nullable id)activityViewController:(UIActivityViewController*)activityViewController itemForActivityType:(NSString *)activityType{
return _filePathUrl;
}
It's work for me.

Related

Memory leaks when loading images to scroller

I have a scrollView in which i load images into from the net .I sometimes get memory warnings, which i assume are because i am doing something wrong with the images loader.
I am trying to fix little things, and i just wanted to show the code here, and hear maybe there are more things i can fix to get rid of this warnings.
So every time the scroller (iPad) has only 4/5 images that are : current page-3->current page+3.
This is how i load the images(every image has also a blur effect with Apple's classes) :
(should i allocated imageView every time? can i improve something here? )
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^
{
NSData *imdata2 = [NSData dataWithContentsOfURL:url];
dispatch_async(dispatch_get_main_queue(), ^
{
UIImage *theImage=[UIImage imageWithData:imdata2 scale:1];
UIImage *LightImage = [theImage applyLightEffect];
UIImage *scaledImage =[resizer resizeImageToWidth:[Globals sharedGlobals].imagesWidth WithImage:theImage];
CGRect viewSizeBack=CGRectMake(scroller.bounds.size.width*toPage , 0, scroller.bounds.size.width, scroller.bounds.size.height);
int x=[Globals sharedGlobals].pageMargins;
int y=([UIScreen mainScreen].bounds.size.height-scaledImage.size.height)/2;
CGRect viewSizeFront=CGRectMake(x , y, scaledImage.size.width,scaledImage.size.height);
UIImageView *backImageView=[[UIImageView alloc] initWithFrame:viewSizeBack];
UIImageView *frontImageView=[[UIImageView alloc] initWithFrame:viewSizeFront];
backImageView.layer.cornerRadius = 0.0;
backImageView.layer.masksToBounds = YES;
backImageView.image=LightImage;
frontImageView.layer.cornerRadius = 0.0;
frontImageView.layer.masksToBounds = YES;
frontImageView.image=scaledImage;
frontImageView.layer.borderWidth=1.0;
frontImageView.layer.borderColor=[UIColor colorWithRed:255.0 green:255.0 blue:255.0 alpha:1.0].CGColor;
[backImageView addSubview:frontImageView];
backImageView.tag=toPage;
frontImageView.tag=toPage;
[scroller addSubview:backImageView];
});
});
You should only ever have 3 images loaded at a maximum - the previous page (if it exists), the current page and the next page.
Any other images you have loaded above this is wasteful because you can't see them and they're just taking up memory for no good reason. If the images aren't too big then you can maintain them in memory and purge them when you get a warning, but for large images this will still generally cause you issues.
If you don't use ARC then add this:
[backImageView autorelease];
[frontImageView autorelease];

How to have an animated background iOS

I want to place an animated background on my app. I have looked into the UIMotionEffect class and yes that does seem beneficial. However, what I am really looking for is something like the dynamic wallpapers provided in iOS settings. The way those colored circles move around is exactly what I am looking for.
I've tried this with no luck:
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"circle"]];
[UIView animateWithDuration:5.0 animations:^{
self.view.backgroundColor = [[UIColor alloc] initWithPatternImage:[UIImage imageNamed:#"circle"]];
}];
My only problem is I have no idea where to start. I looked into OpenGL. I assume it could be done that way, but it seems like a possible rabbit trail that I might not need to take. I also found some videos on YouTube but they involve Adobe Flash, which I do not have. Any suggestions on where to venture for this?
If it's a simple GIF you don't need to get fancy. Just separate the images (many tools to do that) and use the following code (might be some typos):
NSArray *array = [NSArray arrayWithObjects:
[UIImage imageNamed:#"image1.png"],
[UIImage imageNamed:#"image2.png"],
........,
nil];
UIImage *image = [UIImage animatedImageWithImages:array duration:6.0f];
[image startAnimating];

Share MKMapView screenshot

I have a MKMapView and I would like to take a screenshot of it and share it to a social network, for example to Facebook. I've found a nice way to make the screenshot, using MKMapSnapshotter (which is available starting with iOS 7), but my question is: Am I able to share a screenshot of MKMapView? Does Apple allow this?
I found this similar question, but there is not given any clear answer.
Try Google Maps SDK for iOS:
Documentation
And to make the screenshot use the following code:
CGRect rect = [captureView bounds];
UIGraphicsBeginImageContextWithOptions(rect.size,YES,0.0f);
CGContextRef context = UIGraphicsGetCurrentContext();
[captureView.layer renderInContext:context];
UIImage *capturedImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
Yes of course, why would apple object you?
You can surely share the image. As you mentioned you have the image you just need to use default sharing sheet. here's the code:
NSArray *activityItems = [NSArray arrayWithObjects:yourImage, nil];
UIActivityViewController *aActivityView = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:nil];
aActivityView.modalInPopover = UIModalTransitionStyleCoverVertical;
[self presentViewController:aActivityView animated:YES completion:^{
}];
This will present an UIActivityViewController's view which will have share option in it.
Hope this helps.
My gut feeling would be; why wouldn't Apple allow this?
If you have already managed to grab a UIImage representation of your MKMapView using the Apple provided MKMapSnapshotter, I would hazard a guess that Apple have given you the tools you need to do whatever you want with the image so there would be no restrictions as to what you do with it.

Image quality of socially shared image

Problem Resume:
I take a photo with camera or chose one from the library, then add some UITextFields to it (next to UIImageView with the chosen picture), create one UIImage of it all, and then I want to share this, particularly on Facebook and on Twitter. I am able to do this, however the quality of the image drops significantly. How can I adjust the code so that the quality stays on top?
Long description with code and images
First of all, I chose between camera and library. Then, after I pick an image in some way, I get it with
- (void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
method, where I assign the image to my global UIImage *chosenImage, with which I use it afterwards.
Then, I add the chosenImage to the UIImageView, and as a sibling, I add an UITextField, like this:
UIImageView *chosenImageView = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, actualHeight - 50)];
[chosenImageView setBackgroundColor:[UIColor clearColor]];
[chosenImageView setContentMode:UIViewContentModeScaleAspectFill];
[chosenImageView setClipsToBounds:YES];
[chosenImageView setImage:chosenImage];
UITextField *textFieldName = [[UITextField alloc] initWithFrame:CGRectMake(15, 15, 290, 30)];
[textFieldName setBackgroundColor:[UIColor blueColor]];
[textFieldName setDelegate:self];
[textFieldName setTag:-1];
[textFieldName setText:textName];
[textFieldName sizeToFit];
[textFieldName setContentScaleFactor:2.0];
[pageView addSubview:textFieldName];
[pageView addSubview:chosenImageView];
After this, I have a 'share this!' button which, after clicked, presents the possibility to share the image to Facebook and Twitter. I then get the UIImage *imageToShare with this method to convert the UIView to UIImage (which seems to be working alright, imho):
- (UIImage *)changeViewToImage:(UIView *)view
{
UIGraphicsBeginImageContextWithOptions([view bounds].size, NO, 0);
[[view layer] renderInContext:UIGraphicsGetCurrentContext()];
UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return image;
}
It seems that the quality of the shared picture is the same for Facebook and Twitter, and the same in this case means really bad.
the code I use for twitter sharing:
SLComposeViewController *tweetSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeTwitter];
[tweetSheet setInitialText:#""];
[tweetSheet addImage:imageToShare];
[tweetSheet setCompletionHandler:^(SLComposeViewControllerResult result) {
[self dismissViewControllerAnimated:YES completion:nil];
}];
[self presentViewController:tweetSheet animated:YES completion:nil];
and the code I use for Facebook share:
NSDictionary *params = [NSDictionary dictionaryWithObjects:[NSArray arrayWithObjects:UIImagePNGRepresentation(imageToShare), imageDescription, nil] forKeys:[NSArray arrayWithObjects:#"source", #"message", nil]];
[FBRequestConnection startWithGraphPath:#"me/photos" parameters:params HTTPMethod:#"POST" completionHandler:^(FBRequestConnection *connection, id result, NSError *error)
{
[[[UIAlertView alloc] initWithTitle:#"Success!" message:#"Your photo was successfully posted to your Facebook Wall" delegate:nil cancelButtonTitle:#"Ok :)" otherButtonTitles:nil, nil] show];
[self returnFromShareView];
}];
However, I've added some code to save the imageToShare to the documents:
NSData *data = UIImagePNGRepresentation(imageToShare);
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = [paths objectAtIndex:0]; //Get the docs directory
NSString *filePath = [documentsPath stringByAppendingPathComponent:#"currentImage.png"]; //Add the file name
[data writeToFile:filePath atomically:YES]; //Write the file
and when I look it up there, it looks fairly fine! Which really makes me wonder why I don't use an envelope with printed picture (the one saved to the documents, of course!), and don't send it to Menlo Park, CA and South of Market, CA instead of trying to solve this ridiculous issue.
Now come the pictures!
umh.. So after I tried to upload the images here, the uploading thingy turned the .png image to horrible quality as well!!! Aagh, I thought stackOverflow is with me!
Anyways, here are the pictures (uploaded here), and corresponding links, which shows the actual images, on my server (which I hope won't destroy them as well)
Picture uploaded to Facebook: Facebook image on my server
Picture uploaded to Twitter: Twitter image on my server
Picture from the documents: Picture from the documents on my server (there is a huge difference!)
So, does anybody know what settings should I chose for the image in the code to make the quality (even after .jpg compression, which is done everywhere it seems, even here) at least somehow better? And as it seems to me, it happens only on the solid background with text on it (when I tried to upload an image without the background, it looked better, but there must be a way how to make it look better with background as well)
Thanks!
EDIT
As it turns out, the problem might not be with the sharing stuff, but with the jpeg compression itself. As it states here in the answer: Facebook: Ways to preserve image quality of uploaded images?,
"JPEG is not suitable for images with text, large blocks of color, or simple shapes, because crisp lines will blur and colors can shift. http://graphicssoft.about.com/od/graphicformats/f/summary.htm "
So I guess there is no solution, as Facebook, Twitter and even stack.imgur use jpeg compression, and as long as there will be an 'image with text, large blocks of color, or simple shapes', it'll come badly. Too bad.
JPEG compression works best for continuous tone imagery such as photos. It dos not work well with areas of solid color and sharp traditions such as text. Png/Gif works much better. There are some formats that deal with this better such as Google WebP which Facebook considered using but abandoned.
You best best is to stick with JPEG and play with the JPEG encoding setting but there are a few things you can do. Adjust your font either with the built in iOS fonts or use your own custom font. Since sharp transition of solid color cause a problem, avoid using Serif fonts. Also the fatter the font and larger it is the better. IOS supports custom fonts so play around with different open source fonts and find one at the biggest size you can accept. Follow this article
http://codewithchris.com/common-mistakes-with-adding-custom-fonts-to-your-ios-app/.
Another thing that help is anti aliasing. This is where the edge colors are blurred making the text seem more readable(over simplification). The text will not be anti aliased and you can not easily force anti aliasing but you could fake it. Create the text at a larger size (2 to 3x) in a separate image with transparency and scale it down before adding it over the picture. The image interpolation will blur the images giving you a poor mans anti aliasing.

iOS (jailbroken) Displaying application via SBAppContextHostManager

Basically, I'm trying to display an application using the private API SBAppContextHostManager of SpringBoard. So far, I have this code:
SBAppContextHostManager *app = [[objc_getClass("SBAppContextHostManager") alloc] init];
[app setAppBundleID:#"com.apple.springboard"]; // just as an example
[app enableHostingForRequester:#"uniqueID" priority:1];
[app orderRequesterFront:#"uniqueID"];
SBHostWrapperView *view = [app hostViewForRequester:#"uniqueID"];
and after which I call
UIGraphicsBeginImageContextWithOptions([UIScreen mainScreen].bounds.size, YES, [UIScreen mainScreen].scale);
CGContextRef c = UIGraphicsGetCurrentContext();
CGContextSetAllowsAntialiasing(c, YES);
[view.layer renderInContext:c];
UIImage *img = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
to grab a UIImage of the view containing the application. However, the output of this UIImage is completely blank, which leads me to think that my calls to SBAppContextManager are incorrect, thus leading to a blank SBHostWrapperView. Therefore, how should I display an application in this way?
If you are trying to get a preview of the application, rendering an SBHostWrapperView won't work. You see, SBHostWrapperViews don't copy the application's render output, it simply provides a different location on the screen for the app to render to.
Instead, you can use - (SBFullscreenZoomView*)systemGestureSnapshotWithIOSurfaceSnapshotOfApp:(SBApplication*)arg1 includeStatusBar:(BOOL)arg2; in the SBUIController class.
That method returns an SBFullscreenZoomView, a subclass of UIView, with a snapshot of the app provided in arg1. You can use the second snippet of code you provided to get a UIImage of the SBFullscreenZoomView. That should do what you are asking, providing you with a screenshot of only a specific application.

Resources