WKWebview snapshot configuration not supported in iOS 9 - webview

I m getting crash when I try to take snapshot of wkwebview in iOS 9.0,can anyone please help me to resolve this issue?
_webView takeSnapshotWithConfiguration:wkSnapshotConfig completionHandler:^(UIImage * _Nullable snapshotImage, NSError * _Nullable error)

Related

Save Video in RPPreviewController to a specific place instead saving to camera roll?

i´m screen recording with ReplayKit and when the delegate method previewController(_:didFinishWithActivityTypes:) is called when i click the save button, it automatically saves into the camera roll. How can i change that? I want to save the video somwhere on the filesystem on device. I searched all over google and in apple documentation, but i couldn´t find anything relating to that.
If your app supports the app FILES, the replay kit can save file directly to the folder. For example VLC app has a folder in FILES. Otherwise you may need to implement an action extension to do the similar thing.
use this API
- (void)startCaptureWithHandler:(nullable void (^)(CMSampleBufferRef sampleBuffer, RPSampleBufferType bufferType, NSError *_Nullable error))captureHandler completionHandler:(nullable void (^)(NSError *_Nullable error))completionHandler API_AVAILABLE(ios(11.0), tvos(11.0), macos(11.0));
sample code:
-(void)startCapture {
if (#available(iOS 11.0, *)) {
[[RPScreenRecorder sharedRecorder] startCaptureWithHandler:^(CMSampleBufferRef _Nonnull sampleBuffer, RPSampleBufferType bufferType, NSError * _Nullable error) {
if (CMSampleBufferDataIsReady(sampleBuffer) && bufferType == RPSampleBufferTypeVideo) {
NSLog(#"Recording started successfully.");
//save using AVAssetWriter
}
} completionHandler:^(NSError * _Nullable error) {
if (!error) {
NSLog(#"Recording started successfully.");
}else{
NSLog(#"Recording started error %#",error);
}
}];
} else {
// earlier versions issue
}
}
Also: this post may help u somehow
AVAssetWriter Doc

Issue with WebRTC outgoing call (iOS,Kurento)

I'm fairly new to webrtc, and quite experienced in iOS.
We have a media server setup on AWS (all ports open), with kurento one2one client. Everything is working well when I call from desktop to desktop. when I call from desktop to iOS it works (i.e. incoming calls to iOS).
Issue is when I make an outgoing call from iOS to desktop, it doesn't work.
Below are the server logs, so I think call is getting connected...
Received message: {"id":"incomingCall","from":"qqq"}
spec: {"audio":true,"video":{"width":640,"framerate":15}}
chrome: {"audio":true,"video":{"optional":[{"minWidth":640},{"maxWidth":640},{"minFramerate":15},{"maxFramerate":15}]}}
Sending message:{"id":"incomingCallResponse","from":"qqq","callResponse":"accept","sdpOffer”:”huge text, so removed”}
Received message: {"id":"startCommunication","sdpAnswer":"huge text, so removed”}
When call is clicked I'm doing below on iOS:
[peerConnection offerForConstraints:[self defaultOfferConstraints] completionHandler:^(RTCSessionDescription * _Nullable sdp, NSError * _Nullable error) {
[peerConnection setLocalDescription:sdp completionHandler:^(NSError * _Nullable error) {
NSLog(#"%#",error.description);
}];
[[NSOperationQueue mainQueue] addOperationWithBlock:^ {
NSDictionary *registerMessage = #{
#"id": #"call",
#"from": #"qqq",
#"to": #"www",
#"sdpOffer" : sdp.description,
};
NSData *messageData = [NSJSONSerialization dataWithJSONObject:registerMessage
options:NSJSONWritingPrettyPrinted
error:nil];
NSString *messageString =
[[NSString alloc] initWithData:messageData encoding:NSUTF8StringEncoding];
[webSocket send:messageString];
}];
}];
and after I get accept response I do below,
if ([answerID isEqualToString:#"callResponse"]) {
NSString *answerRespose = [wssMessage objectForKey:#"response"];
if ([answerRespose isEqualToString:#"accepted"]) {
description = [[RTCSessionDescription alloc] initWithType:RTCSdpTypeAnswer sdp:sdpAnswer];
[peerConnection setRemoteDescription:description completionHandler:^(NSError * _Nullable error) {
}];
}
}
I'm also taking care of ICECandidates...
As incoming works without any issue, I'm assuming that no mistake was made in creating stream.
Am I missing something for outgoing call?
I finally found it out.
Issue was with ICECandidates, I came to know that adding ICECandidate after setting remote description works.
Made an array ICECandidates collected from web socket and added them once I got remote RemoteDescription :)
I hope this helps someone in future.

GKGameSession- saveData always fails with malloc error after getShareURLWithCompletionHandler

I'm trying to incorporate GKGameSession into my Game Center game. I've tried several combinations of the following code: running the commands asynchronously, chaining them in the completion handlers, etc. Every time I see the same result: I can use saveData just fine until I've called getShareURLWithCompletionHandler. After that, any attempt to saveData throws an error.
Here's the simplest version of code that exhibits the problem:
CKContainer *defaultContainer = [CKContainer defaultContainer];
[GKGameSession createSessionInContainer:defaultContainer.containerIdentifier
withTitle:#"temp title"
maxConnectedPlayers:4
completionHandler:^(GKGameSession * _Nullable session, NSError * _Nullable error)
{
if (error)
{
[self printError:error];
}
[session getShareURLWithCompletionHandler:^(NSURL * _Nullable url, NSError * _Nullable error)
{
if (error)
{
[self printError:error];
}
}];
NSData *newData = [NSData dataWithBytesNoCopy:#"abcdefghijklmnopqrstuvwxyz" length:26];
[reSession saveData:newData completionHandler:^(NSData * _Nullable conflictingData, NSError * _Nullable error)
{
if (error)
{
[self printError:error];
}
}];
}];
In most cases, the saveData call simply crashes:
malloc: *** error for object 0x32df14: pointer being freed was not allocated
*** set a breakpoint in malloc_error_break to debug
But sometimes it throws an error:
GKGameSessionErrorDomain:GKGameSessionErrorUnknown
I've tried different kinds of data being saved. I've tried making the calls sequential by chaining all the calls in completion handlers. I've tried doing the URL fetch and data save inside and outside of the creationSession completion handler.
Is there something I'm doing wrong here?
I see the same, but with a more useful error:
The requested operation could not be completed because the session has been updated on the server, causing a conflict.
The save documentation says,
It is up to the developer to decide how to handle save conflicts.
Here though, retrying the save fails every time, forever. So yeah, that's the same state you're in.
However, when the player joining the game enters the URL on their device, their GKGameSessionEventListener's didAddPlayer: is called, and then if they save... they get the same conflict error, but if they then retry the save... it works!
The player creating the link is locked out of saving or updating game state, until joining players have updated the data. When the other player saves, the original player gets a call to session:player:didSave: on the GKGameSessionEventListener.
At that point the original player can then save as expected.
You should put one block inside other. Because blocks may be completed in any order.
I have working code like this:
NSData *newData = [NSData dataWithBytesNoCopy:#"abcdefghijklmnopqrstuvwxyz" length:26];
[reSession saveData:newData completionHandler:^(NSData * _Nullable conflictingData, NSError * _Nullable error)
{
if (error)
{
[self printError:error];
} else {
[session getShareURLWithCompletionHandler:^(NSURL * _Nullable url, NSError * _Nullable error)
{
if (error)
{
[self printError:error];
}
}];
}
}];

Error when using -[MPMediaPlaylist addItemWithProductID:completionHandler:]

I'm trying to use the new Apple Music APIs from 9.3 to add a song to a playlist created by my app, without adding it to the user's library.
Consider the productID 316654632, it's the song Lisztomania by Phoenix, in the US iTunes Store.
Using the following code, I can play the song
MPMusicPlayerController *musicPlayer = [MPMusicPlayerController systemMusicPlayer];
[musicPlayer setQueueWithStoreIDs:#[#"316654632"]];
[musicPlayer play];
Using the following code, I can add the song to my Apple Music library
[[MPMediaLibrary defaultMediaLibrary] addItemWithProductID:#"316654632" completionHandler:^(NSArray<__kindof MPMediaEntity *> * _Nonnull entities, NSError * _Nullable error) {
NSLog(#"%#", error);
}];
Error is nil, and I can see the song in my library.
But trying the same with a playlist doesn't work.
[[MPMediaLibrary defaultMediaLibrary] getPlaylistWithUUID:uuid creationMetadata:[[MPMediaPlaylistCreationMetadata alloc] initWithName:#"Test Playlist"] completionHandler:^(MPMediaPlaylist * _Nullable playlist, NSError * _Nullable error) {
NSLog(#"%#", error);
if (!error) {
[playlist addItemWithProductID:#"316654632" completionHandler:^(NSError * _Nullable error) {
NSLog(#"%#", error);
}];
}
}];
The playlist is created, I can see it in Music.app, but when I try to add the same product ID I played & added to my library to the playlist, I get an error
Error Domain=MPErrorDomain Code=4 "The requested id could not be found" UserInfo={NSLocalizedDescription=The requested id could not be found}
But how could it not be found if I successfully added the same item to my library?
UPDATE
Good news! Apple has fixed rdar://26408683 on 10.2.1!
In my playlist conversion app (mixlib), the only solution I have found to reliably add some tracks to a newly created playlist is to wait.
In my tests, waiting five seconds seems to be enough.
[[MPMediaLibrary defaultMediaLibrary] getPlaylistWithUUID:uuid creationMetadata:[[MPMediaPlaylistCreationMetadata alloc] initWithName:#"Test Playlist"] completionHandler:^(MPMediaPlaylist * _Nullable playlist, NSError * _Nullable error) {
if (!error) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, 5 /*seconds*/ * NSEC_PER_SEC), dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0)), ^() {
[playlist addItemWithProductID:#"316654632" completionHandler:^(NSError * _Nullable error) {
NSLog(#"%#", error);
}];
}
}];
I suspect it is a server/network related issue because it sometimes works without waiting. The "requested id" which is not found may be the playlist id, not the track id.
When it starts to work for a playlist, then it will always work. So you don't need to wait before adding each additional track, but only before adding the first one.

HKAnchoredObjectQuery deleted objects is empty in iOS 9.0 but works fine with iOS 9.2.1. Is this a update in iOS 9.2?

HealthKit's HKAnchoredObjectQuery is not returning deleted objects in iOS 9.0. Even if i delete a object and then add a object the deleted objects array is always empty (except on the first launch of app).
But the same code works fine with iOS 9.2.1. The deleted objects are returned whenever a object is added to health app and observer query is fired.
Is this some new update in iOS 9.2.1 and the bug with deleted objects is resolved in this version?
I could not find any Apple documentation confirming this.
Edit:
The code firing the query is
NSPredicate* predicate = [HKQuery predicateForSamplesWithStartDate: [NSDate dateWithTimeIntervalSinceNow:-172800.0] endDate:nil options:0];
HKAnchoredObjectQuery *query =
[[HKAnchoredObjectQuery alloc]
initWithType:sampleType
predicate:predicate
anchor:anchor
limit:HKObjectQueryNoLimit
resultsHandler:^(HKAnchoredObjectQuery * _Nonnull query,
NSArray<__kindof HKSample *> * _Nullable sampleObjects,
NSArray<HKDeletedObject *> * _Nullable deletedObjects,
HKQueryAnchor * _Nullable newAnchor,
NSError * _Nullable error) {
}];
This is a bug was a bug in iOS 9.0 that was fixed in 9.1. You can work around the issue by not specifying a predicate that constrains on the startDate or endDate of HKSample.

Resources