NSItemProviderCompletionHandler urlHandler = ^(NSURL *url, NSError *error) {
my_url = url.absoluteString;
};
if ([itemProvider hasItemConformingToTypeIdentifier:#"public.url"]) {
[itemProvider loadItemForTypeIdentifier:#"public.url" options:nil completionHandler:urlHandler];
}
[self finishSelectingPost:itemProvider data:data];
how do I run the last line after my_url value changed ? thanks ~!
It is not clear what is my_url and where is data, but supposing they are valid in the context of provided code snapshot, the handler could be as following
__weak __typeof(self) weakSelf = self;
NSItemProviderCompletionHandler urlHandler = ^(NSURL *url, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
my_url = url.absoluteString;
[weakSelf finishSelectingPost:itemProvider data:data];
}
};
Related
I am using OneDriveSDK for iOS . I am unable to find streamable Path for any file.
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
__block NSString *streamablePath = #"";
ODClient *client = [ODClient loadCurrentClient];
ODItemRequest *request = [[[client drive] items:item.path] request];
[request getWithCompletion:^(ODItem *response, NSError *error) {
if (!error)
{
streamablePath = [[response dictionaryFromItem] objectForKey:#"#content.downloadUrl"];
dispatch_semaphore_signal(sema);
}
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
return streamablePath;
I am using a MTBBarcodeScanner interface to implement a barcode scanner application.
I need to get the still image of the scanner in my code, so I am trying to call the function:
- (void)captureStillImage:(void (^)(UIImage *image, NSError *error))captureBlock {
if ([self isCapturingStillImage]) {
if (captureBlock) {
NSError *error = [NSError errorWithDomain:kErrorDomain
code:kErrorCodeStillImageCaptureInProgress
userInfo:#{NSLocalizedDescriptionKey : #"Still image capture is already in progress. Check with isCapturingStillImage"}];
captureBlock(nil, error);
}
return;
}
AVCaptureConnection *stillConnection = [self.stillImageOutput connectionWithMediaType:AVMediaTypeVideo];
if (stillConnection == nil) {
if (captureBlock) {
NSError *error = [NSError errorWithDomain:kErrorDomain
code:kErrorCodeSessionIsClosed
userInfo:#{NSLocalizedDescriptionKey : #"AVCaptureConnection is closed"}];
captureBlock(nil, error);
}
return;
}
[self.stillImageOutput captureStillImageAsynchronouslyFromConnection:stillConnection
completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error) {
if (error) {
captureBlock(nil, error);
return;
}
NSData *jpegData = [AVCaptureStillImageOutput jpegStillImageNSDataRepresentation:imageDataSampleBuffer];
UIImage *image = [UIImage imageWithData:jpegData];
if (captureBlock) {
captureBlock(image, nil);
}
}];
}
From my viewcontroller I am calling this function like:
UIImage *img;
NSError *e;
[_scanner captureStillImage:img :e];
but giving me the error:
No visible #interface for 'MTBBarcodeScanner' declares the selector 'captureStillImage::
How can I call this function my UIViewcontroller subclass?
The syntax of your block is incorrect. It should be the following:
[_scanner captureStillImage:^(UIImage *image, NSError *error) {
}];
Also, this is a callback function, you are not supposed to feed parameters into it, these are being returned from it.
If you would like to have variables representing the return values of the callback function outside you callback, you need to declare __block variables.
__block UIImage* img;
__block NSError* e;
[_scanner captureStillImage:^(UIImage *image, NSError *error) {
img = image;
e = error;
}];
I want to share both text and URL from host app using sharing extension.
- (BOOL)isContentValid {
for (NSExtensionItem *item in self.extensionContext.inputItems) {
for (NSItemProvider *itemProvider in item.attachments) {
if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeURL ]) {//
[itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeURL options:nil completionHandler:^(NSURL *url, NSError *error) {
if(url ) {
self.linksURL= [url absoluteString];
}
}];
}
else if ([itemProvider hasItemConformingToTypeIdentifier:(NSString *)kUTTypeText ])
{
[itemProvider loadItemForTypeIdentifier:(NSString *)kUTTypeText options:nil completionHandler:^(NSURL *url, NSError *error) {
if(url ) {
self.linkTitleText= [url absoluteString];
}
}];
}
}
}
self.charactersRemaining=#85;
return YES;
}
Most of this is correct but the implementation of the method is wrong as you will return TRUE before anything has happened. Instead of doing it this way I suggest using a method with a completion handler like so...
-(void)contentURL:(NSExtensionItem *)extension completion:(void (^)(NSURL *url))completion {
for (NSItemProvider *items in self.shareItem.attachments) {
if ([items hasItemConformingToTypeIdentifier:(NSString *)kUTTypeURL]) {
[items loadItemForTypeIdentifier:(NSString *)kUTTypeURL options:nil completionHandler:^(NSURL *url, NSError *error) {
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
completion(url);
}];
}];
}
}
}
Then create a similar method for the text attribute.
P.S Don't forget to put the operation in a block
I am using Parse.com
When I download my PFFile(contains image) in viewDidAppear my app freezes for a while and then it shows the pic. But that is not right. I want UIActivityIndicatorView to be animated or at least shown. I know that this deals with async or something. But I have no idea how to make that work correctly.
PFFile* imageFile = [[PFUser currentUser] objectForKey:#"profilePic"];
if (imageFile) {
self.activity.hidden = NO;
[self.activity startAnimating];
NSURL* imageFileUrl = [[NSURL alloc]initWithString:imageFile.url];
NSData* imageData = [NSData dataWithContentsOfURL:imageFileUrl];
self.profilePic.image = [UIImage imageWithData:imageData];
}
This downloads the image and shows it.
UPD:
PFQuery* query = [PFUser query];
[query valueForKey:#"profilePic"];
[query findObjectsInBackgroundWithBlock:^(NSArray* data, NSError* error)
{
PFFile* imageFile = data[0];
[imageFile getDataInBackgroundWithBlock:^(NSData* data,NSError* error){
if (!error) {
self.activity.hidden = NO;
[self.activity startAnimating];
NSURL* imageFileUrl = [[NSURL alloc]initWithString:imageFile.url];
NSData* imageData = [NSData dataWithContentsOfURL:imageFileUrl];
self.profilePic.image = [UIImage imageWithData:imageData];
}else{
self.profilePic.image = [UIImage imageNamed:#"profile#2.png"];
}
}];
}];
UPD 2:
This solved my problem. Both answers were helpful.
PFQuery* query = [PFUser query];
[query getObjectInBackgroundWithId:[PFUser currentUser].objectId block:^(PFObject* object, NSError* error){
if(!error){
PFFile* imageFile = object[#"profilePic"];
[imageFile getDataInBackgroundWithBlock:^(NSData* data, NSError* error) {
if (!error) {
self.activity.hidden = NO;
[self.activity startAnimating];
self.profilePic.image = [UIImage imageWithData:data];
NSLog(#"Profile pic shown");
}
else{
NSLog(#"Error 2: %#",error);
}
}];
}else{
self.profilePic.image = [UIImage imageNamed:#"profile#2.png"];
NSLog(#"Fail 1 : %#",error);
}
}];
This is because you are not getting the object in the background. Try using a query to accomplish this. If you need more info I can give you the full query as I have this code inside my app :)
Sample code:
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {}];
To get an image with data:
PFFile *imageFile = [object objectForKey:#"YOURKEY"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {}];
There are couple of things wrong with your code
Your query is not right, I can't understand this part [query valueForKey:#"profilePic"]; if you want to get user have profile pics then you should do something like this [query whereKeyExist:#"profilePic"];, but at the moment query you have will bring down all objects.
You are downloading image in main thread which make your app free you should do something like this
[imageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
if (!error)
{
self.profilePic.image = [UIImage imageWithData:imageData];
}
}];
You must check data.count before calling data[0], this could crash your application if data array is nil or empty.
Update:
Getting profile pic for currentUser will be something like this
PFUser *currentUser = [PFuser currentUser];
if (!currentUser)
{
//need to login
}
else
{
// may be you need to fetch
__weak typeof(self) weakSelf = self;
[currentUser fetchIfNeededInBackgroundWithBlock:^(PFObject *obj, NSError *error){
PFFile* imageFile = [[PFUser currentUser] objectForKey:#"profilePic"];
[imageFile getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
if (!error)
{
weakSelf.profilePic.image = [UIImage imageWithData:imageData];
}
}];
}];
}
I'm trying to get an image asynchronously from an url with AFNetworking 2.0
My problem is that neither success nor failure are called
I've checked my URL in a browser so the problem is not here
UIImageView *imgv = [[UIImageView alloc] init];
[imgv setImageWithURLRequest:myURL
placeholderImage:nil
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
/*some code*/
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
/*some code*/
];
When I look deeper inside setImageWithUrlRequest:placeholderImage:success:failure
__weak __typeof(self)weakSelf = self;
self.af_imageRequestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
self.af_imageRequestOperation.responseSerializer = self.imageResponseSerializer;
[self.af_imageRequestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
if ([[urlRequest URL] isEqual:[strongSelf.af_imageRequestOperation.request URL]]) {
if (success) {
success(urlRequest, operation.response, responseObject);
} else if (responseObject) {
strongSelf.image = responseObject;
}
if (operation == strongSelf.af_imageRequestOperation){
strongSelf.af_imageRequestOperation = nil;
}
}
[[[strongSelf class] sharedImageCache] cacheImage:responseObject forRequest:urlRequest];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
__strong __typeof(weakSelf)strongSelf = weakSelf;
if ([[urlRequest URL] isEqual:[strongSelf.af_imageRequestOperation.request URL]]) {
if (failure) {
failure(urlRequest, operation.response, error);
}
if (operation == strongSelf.af_imageRequestOperation){
strongSelf.af_imageRequestOperation = nil;
}
}
}];
My code goes trought [self.af_imageRequestOperation setCompletionBlockWithSuccess:^( AFHTTPRequestOperation *operation, id responseObject) {
with success but i've noticed that __strong __typeof(weakSelf)strongSelf = weakSelf; are both nil
Any idea?
Your imgv is never retained so it will be released after current scope so in your block weakSelf will be release when image is successfuly downloaded so thats why you are getting nil.