The documents say to use this in swift:
let cameraViewController = CameraViewController { [weak self] image, asset in
// Do something with your image here.
self?.dismiss(animated: true, completion: nil)
}
present(cameraViewController, animated: true, completion: nil)
But I don't know how to convert this to Objective C.
It's just clever looking code because he's got Swift default values in the initializer for CameraViewController. Objective-C does not support default values, so you need to provide them. The source is right here.
Something like this:
croppingParameters: CroppingParameters = CroppingParameters(),
allowsLibraryAccess: Bool = true,
allowsSwapCameraOrientation: Bool = true,
allowVolumeButtonCapture: Bool = true,
completion: #escaping CameraViewCompletion
__weak typeof(self) weakSelf = self;
CameraViewController *cameraViewController = [[CameraViewController alloc]
initWithCroppingParameters:[CroppingParameters new]
allowsLibraryAccess: YES
allowsSwapCameraOrientation: YES
allowVolumeButtonCapture: YES
completion: ^(UIImage *image, PHAsset *asset) {
[weakSelf dismissViewControllerAnimated:YES completion:nil];
}];
[self presentViewController:cameraViewController animated:YES completion:nil];
But since the ALCamera project doesn't seem to care that much about Objective-C, there might not be full support for it.
Related
I successfully implemented imglyKit in my Objective-C code, this library is made in swift language. Now i am opening a IMGLYMainEditorViewController from my viewcontroller.
My problem is that when the image is edited and when i press the done button i did not get the edited image. I checked the code and show that they set the completion block when they open IMGLYMainEditorViewController.
This is the code which is written in the library.
let editorViewController = IMGLYMainEditorViewController()
editorViewController.highResolutionImage = image
if let cameraController = cameraController {
editorViewController.initialFilterType = cameraController.effectFilter.filterType
editorViewController.initialFilterIntensity = cameraController.effectFilter.inputIntensity
}
editorViewController.completionBlock = editorCompletionBlock
private func editorCompletionBlock(result: IMGLYEditorResult, image: UIImage?) {
if let image = image where result == .Done {
UIImageWriteToSavedPhotosAlbum(image, self, "image:didFinishSavingWithError:contextInfo:", nil)
}
dismissViewControllerAnimated(true, completion: nil)
}
I wrote this code in my controller.
IMGLYMainEditorViewController *temp view = [[IMGLYMainEditorViewController alloc]init];
view.highResolutionImage = self.image_view.image;
[self.navigationController pushViewController:view animated:YES];
I want to set a block method here when i open a IMGLYMainEditorViewControlle so that i am able to get that edited image.
I did lots of try but not able to do that because i did not have a much knowledge about the block and how to deal with that. so please help me because i stuck here.
Remove the space between "temp view" instance name,
This is how you provide a completion block to an object:
IMGLYMainEditorViewController *tempView = [[IMGLYMainEditorViewController alloc] init];
tempView.completionBlock = ^(IMGLYEditorResult result, UIImage *image){
view.highResolutionImage = image;
};
[self.navigationController pushViewController:view animated:YES];
I have an application which uses UIActivityViewController to share a link with NSExtensionActivationSupportsWebURLWithMaxCount like so:
NSURL *shareUrl = [NSURL URLWithString:[[sarray valueForKey:#"url"] description]];
NSString* someText = #"";
NSArray* dataToShare = #[shareUrl,someText]; // ...or whatever pieces of data you want to share.
NSArray *appActivities = [NSArray arrayWithObjects:[[UIActivity alloc] init], nil];
UIActivityViewController* activityViewController = [[UIActivityViewController alloc] initWithActivityItems:dataToShare applicationActivities:appActivities];
activityViewController.excludedActivityTypes=#[UIActivityTypeAddToReadingList,UIActivityTypeAirDrop,UIActivityTypePrint,UIActivityTypeAssignToContact];
[self.navigationController presentViewController:activityViewController animated:YES completion:nil];
[activityViewController setCompletionWithItemsHandler:^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
if (!completed) return;
}];
Except for Instagram, all options are coming up in the UIActivityViewController.
Can anyone help me discover where I am going wrong or is this by default?
By default iOS doesn't have support for instagram. U might need to use 3rd party libraries.
For iOS 6 and above, you can use this UIActivity to upload images to Instagram which has the same workflow using iOS hooks but simplifies development.
Try this library
DMActivityInstagram
Swift 4.0+
To get the instagram app to show in the icon list, you must share an UIImage object in your dataToShare array.
I ran into a problem where my shared items contained a URL and an UIImage, and when sharing to iMessages I only wanted the URL to be shared and not the UIImage.
To solve this I made the presenting UIViewController conform to UIActivityItemSource protocol like so:
extension PresentingViewController: UIActivityItemSource {
public func activityViewControllerPlaceholderItem(_ activityViewController: UIActivityViewController) -> Any {
UIImage() // This allows instagram app to show as a choice
}
public func activityViewController(_ activityViewController: UIActivityViewController, itemForActivityType activityType: UIActivity.ActivityType?) -> Any? {
guard let items = self.items else { return nil } // items to present
switch activityType! {
case .message, .postToTwitter, .copyToPasteboard, .mail:
return items.first(where: { $0 is URL })
default: // this catches the case where IG is tapped
return items.first(where: { $0 is UIImage }) as? UIImage
}
}
}
and instead of passing in an array of Activity Items that contain the object you want to share, you pass in the PresentingViewController like so:
// set up activity view controller
activityVC = UIActivityViewController(
activityItems: [PresentingViewController.self],
applicationActivities: [instaGramActivity]
)
self.present(activityVC, animated: true, completion: nil)
Instagram option will not be available with only text. For displaying instagram option in activity controller, you need to pass url object with text, or only url object else you can pass only image to share items which will enable instagram option for you.
TWPhotoPickerController *photoPicker = [[TWPhotoPickerController alloc] init];
photoPicker.cropBlock = ^(UIImage *image) {
//do something
};
[self presentViewController:photoPicker animated:YES completion:NULL];
Been stuck on this for way too long. I have imported all the correct header files into my bridging header file... just need to know how do I translate this block into swift syntax?
It should be something like this:
var photoPicker = TWPhotoPickerController()
photoPicker.cropBlock = { (image: UIImage) -> () in
// do something
}
presentViewController(photoPicker, animated: true, completion: nil)
I am tring to open appstore page as model view inside application using following code
[NSDictionary dictionaryWithObject:#"APPID" forKey:SKStoreProductParameterITunesItemIdentifier];
SKStoreProductViewController *productViewController = [[SKStoreProductViewController alloc] init];
[self presentViewController:productViewController animated:YES completion:nil];
but when appstore is open inside application, it is opening as blank page.
Please refer screenshoot attached
I dont understand why appstore page of my app is not opening. I am passing APPID in above code.
Is there any other way to rate application without closing app ?
basically, something like this could help on you, after you linked the StoreKit.framework to your project. please note, it may not be working on simulator; on real device it works well.
.h
#interface UIYourViewController : UIViewController <SKStoreProductViewControllerDelegate> { }
.m
- (void)myOwnCustomMethod {
SKStoreProductViewController *_controller = [[SKStoreProductViewController alloc] init];
[_controller setDelegate:self];
[_controller loadProductWithParameters:[NSDictionary dictionaryWithObjectsAndKeys:#"364709193", SKStoreProductParameterITunesItemIdentifier, nil] completionBlock:^(BOOL result, NSError *error) {
if (result) {
[self.navigationController presentViewController:_controller animated:TRUE completion:nil];
} else {
// you can handle the error here, if you'd like to.
}
}];
}
#pragma mark - <SKStoreProductViewControllerDelegate>
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
[self dismissViewControllerAnimated:TRUE completion:nil];
}
In Swift 3,
import StoreKit
class DetailViewController: UIViewController {
#IBAction func onEditButton(_ sender: UIBarButtonItem) {
let vc = SKStoreProductViewController()
vc.delegate = self
present(vc, animated: true, completion: nil)
vc.loadProduct(withParameters: [SKStoreProductParameterITunesItemIdentifier: 351091731]) { (success, error) in
if !success {
print("\(error)")
}
}
}
}
extension DetailViewController: SKStoreProductViewControllerDelegate {
func productViewControllerDidFinish(_ viewController: SKStoreProductViewController) {
viewController.dismiss(animated: true, completion: nil)
}
}
Make sure SKStoreProductParameterITunesItemIdentifier's value is Number, as stated in its head file, though String value is currently OK.
I'm using UIActivityItemProvider subclass to provide custom data. But sometimes getting data fails and I don't want to present activity (e.g. message composer). Tried [self cancel] and return nil; in item method, but message composer still shows (with empty message).
If you dismiss the UIActivityViewController before returning from -(id)item it will not present the users chosen activity.
To do this you first need to grab the activityViewController in activityViewControllerPlaceholderItem. In -(id)item run code in a dispatch_async to update progress and dismiss on complete / error which I'm doing using a promise lib.
In your subclass of UIActivityItemProvider do something similar to the example below.
-(id) activityViewControllerPlaceholderItem:(UIActivityViewController *)activityViewController
{ self.avc = activityViewController;
return NSURL;
}
-(id)item
{ __block BOOL fileProcDone = NO;
dispatch_async(dispatch_get_main_queue(), ^
{ self.pvc = [[ProgressAlertVC alloc] init];
[self.vc presentViewController:self.pvc animated:YES completion:nil];
[[[[self promiseMakeFile]
progressed:^(float progress)
{ self.pvc.progress = progress;
}]
fulfilled:^(id result)
{ [self.pvc dismissViewControllerAnimated:YES completion:^
{ fileProcDone = YES;
}];
}]
failed:^(NSError *error)
{ [self.pvc dismissViewControllerAnimated:YES completion:^
{ [self.vc dismissViewControllerAnimated:YES completion:^
{ fileProcDone = YES;
}];
}];
}];
});
while (!fileProcDone)
{ [NSThread sleepForTimeInterval:0.1];
};
return NSURL;
}
This will result in a console log message from activity extensions but as long as they deal correctly with errors things should be fine. If you return nil from -(id)activityViewController: itemForActivityType: you don't get console errors but will get the users chosen activity even if you dismiss the UIActivityViewController at this point.
You simply need to call the cancel method of UIActivityItemProvider. Since UIActivityItemProvider is an NSOperation, calling cancel will mark the operation cancelled.
At that point, you have a few options to actually stop the long running task, depending on the structure of your task. You could override the cancel method and do your cancellation there, just be sure to call [super cancel] as well. The second option is the check the value of isCancelled within the item method.
An example item provider
import UIKit
import Dispatch
class ItemProvider: UIActivityItemProvider {
override public var item: Any {
let semaphore = DispatchSemaphore(value: 0)
let message = "This will stop the entire share flow until you press OK. It represents a long running task."
let alert = UIAlertController.init(title: "Hello", message: message, preferredStyle: .alert)
let action = UIAlertAction.init(title: "OK", style: .default, handler:
{ action in
semaphore.signal()
})
let cancel = UIAlertAction.init(title: "CANCEL", style: .destructive, handler:
{ [weak self] action in
self?.cancel()
semaphore.signal()
})
alert.addAction(action)
alert.addAction(cancel)
//Truly, some hacking to for the purpose of demonstrating the solution
DispatchQueue.main.async {
UIApplication.shared.delegate?.window??.rootViewController?.presentedViewController!.present(alert, animated: true, completion: nil)
}
// We can block here, because our long running task is in another queue
semaphore.wait()
// Once the item is properly cancelled, it doesn't really matter what you return
return NSURL.init(string: "blah") as Any
}
}
In the view controller, start a share activity like this.
let provider = ItemProvider.init(placeholderItem: "SomeString")
let vc = UIActivityViewController.init(activityItems: [provider], applicationActivities: nil)
self.present(vc, animated: true, completion: nil)