ios10 directory extension send some strange error messages - ios10

I try to develop an extension to identify incoming call phoneNumber, but there were some errores during my developing , which i never have met before.
The app seems to work when i test API for this extension.
But when i used For cycle (for...in...) to add identification like this
CXCallDirectoryPhoneNumber phoneNumber = model.COL_NUM2.longLongValue;
[context addIdentificationEntryWithNextSequentialPhoneNumber:phoneNumber label:content];
it comes to send two error messages at this function.
CXCallDirectoryManager *manager = [CXCallDirectoryManager sharedInstance];
[manager reloadExtensionWithIdentifier:extensionIdentifier completionHandler:^(NSError * _Nullable error) {}];
If my cycle count is more than 20 the error code is 2 which means CXErrorCodeCallDirectoryManagerErrorLoadingInterrupted. If cycle count is less than 20 and the parameter, which is called content in this demo, contains a special string, which is just an normal name, the error code is 3 that means CXErrorCodeCallDirectoryManagerErrorEntriesOutOfOrder.
I don't know how to solve this problem after i searched it in google and baidu and got none useful answer.

Related

Geocoding address into coordinates in iPhone

I am trying to geocode address into coordinates using following code:
CLGeocoder *geocoder = [[CLGeocoder alloc] init];
[geocoder geocodeAddressString:#"6138 Bollinger Road, San Jose, United States" completionHandler:^(NSArray* placemarks, NSError* error){
for (CLPlacemark* aPlacemark in placemarks)
{
// Process the placemark.
NSString *latDest1 = [NSString stringWithFormat:#"%.4f",aPlacemark.location.coordinate.latitude];
NSString *lngDest1 = [NSString stringWithFormat:#"%.4f",aPlacemark.location.coordinate.longitude];
lblDestinationLat.text = latDest1;
lblDestinationLng.text = lngDest1;
}
}];
I have tried it many times but the debugger never enters the block and I am not able to get the location. What can I try next?
All right I found my mistake.
The code is correct and works perfect. All the while I was working on it was through debugger and was trying to figure out why the debugger did not enter the block. But now I have found out debugger does not enter the block at that moment. It takes little in getting the location values. It is done asynchronously so I was not able to find it and I was getting crash because of no values just after the crash. I have moved my code post block to inside the block and everything works fine for me now.
I just ran that exact code and it worked as expected. Make sure that you have an active internet connection.
Try adding a NSLog on the strings and see if it gets called.
NSLog(#"lat: %#, lng: %#", latDest1, lngDest1);
Are you running it in the simulator or the device?
Blocks are new features to Objective C from iOS4.0 onwards. A block you can imagine as a delegate method working in same functional block. As for any delegate method it takes time to invoke, depending upon the condition, same way block executes the code inside it, when it completes its work of geocoding. You can read more about Block in apples documentation or read http://www.raywenderlich.com/9438/how-to-use-blocks-in-ios-5-tutorial-part-2.
You can also have look into my repository on GITHUB https://github.com/Mangesh20/geocoding

ProductName length cause connection problem

It seems incredible but if I put a productName (not BundleNamethat appears in home screen) longer than 10 chars my app works well except from I'm not able to get response of my connection requets.
I mean...for example if I put APPNAME123 in productName I obtain APPNAME123.app and all works fine.
If i put APPNAME1234 in productName I obtain APPNAME1234.app and app works except for connections methods...for example if I call www.mydomain.com/example.asp I got no errors, but zero bytes as response!!!!
I use
NSURLRequest *request=[NSURLRequest requestWithURL:MYURL];
NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
and result is not nil but with zero length while error is nil
Of course I tried in various way (both on simulator and device), cleaning and rebuilding project avery time, and of course I tried with other names...same results..if longer than 10 chars I got same problems!
I've also created a new project with desired name longer than 10 chars and I got the same problem.
That made me crazy for a whole day...because I didn't find a specification for this and the rest of app wiorking good!!!
I'd like to know:
1) if anyone else notice this or itis just my problem, maybe some dirty on my mac
2) if there some documentation about this everywhere
thanks in advance for your answers
that doesn't sound like your problem, sounds totally unrelated, perhaps remove products from simulator and do a clean and build. My guess is that you have 2 copies, one working and one broken on the simulator, and it is launching the wrong one.
Sounds more like a memory issue. What's about response, do you read it immediately? What if appname has a length of 12, 13, ... characters, any change than? Have you tried to have a look into memory browser before/after calling sendSyncRequest?

Where is NSAlert.h in the iOS SDK?

According to iOS's Using and Creating Error Objects, one can display a error object with the following code.
NSError *theError = nil;
BOOL success = [myDoc writeToURL:[self docURL] ofType:#"html" error:&theError];
if (success == NO) {
// Maybe try to determine cause of error and recover first.
NSAlert *theAlert = [NSAlert alertWithError:theError];
[theAlert runModal]; // Ignore return value.
}
Unfortunately, I am not smart enough to figure out how to include NSAlert.h.
Any help would be appreciated.
That document is referring to the (OS X) AppKit framework. Right after that box, it says:
(UIAlertView, the UIKit class corresponding to NSAlert, has no equivalent method for alertWithError:.)
You can still use UIAlertView, but you'll need to manually populate the title, message, and button strings from the error.
NSAlert isn't availble in UIKit. the example it just an copy past of the OS X doc.
This code in Listing 2-1 uses the
returned NSError to display an error
alert to the user immediately.
(UIAlertView, the UIKit class
corresponding to NSAlert, has no
equivalent method for
alertWithError:.) Error objects in the
Cocoa domain are always localized and
ready to present to users, so they can
often be presented without further
evaluation.
Its in the AppKit framework.
NSAlert
Import that framework to your project in xcode, then use the #include directive at the top of your code
there are also some samples of using NSAlert if you go to that page and look at the "Sample Code". I always do that if I'm unsure of any part of a new framework

How to use AVCaptureSession to stream live preview video, then take a photo, then return to streaming

I have an application that creates its own live preview prior to taking a still photo. The app needs to run some processing on the image data and thus is not able to rely on AVCaptureVideoPreviewLayer. Getting the initial stream to work is going quite well, using Apple's example code. The problem comes when I try to switch to the higher quality image to take the snapshot. In response to a button press I attempt to reconfigure the session for taking a full resolution photo. I've tried many variations but here is my latest example (which still does not work):
- (void)sessionSetupForPhoto
{
[session beginConfiguration];
session.sessionPreset = AVCaptureSessionPresetPhoto;
AVCaptureStillImageOutput *output = [[[AVCaptureStillImageOutput alloc] init] autorelease];
for (AVCaptureOutput *output in [session outputs]) {
[session removeOutput:output];
}
if ([session canAddOutput:output]){
[session addOutput:output];
} else {
NSLog(#"Not able to add an AVCaptureStillImageOutput");
}
[session commitConfiguration];
}
I am consistently getting an error message just after the commitConfiguration line that looks like this:
(that is to say, I am getting an AVCaptureSessionRuntimeErrorNotification sent to my registered observer)
Received an error:
NSConcreteNotification 0x19d870 {name
= AVCaptureSessionRuntimeErrorNotification;
object = ;
userInfo = {
AVCaptureSessionErrorKey = "Error Domain=AVFoundationErrorDomain
Code=-11800 \"The operation
couldn\U2019t be completed.
(AVFoundationErrorDomain error
-11800.)\" UserInfo=0x19d810 {}";
The documentation in XCode ostensibly provides more information for the error number (-11800), "AVErrorUnknown - Reason for the error is unknown.";
Previously I had also tried calls to stopRunning and startRunning, but no longer do that after watching WWDC Session 409, where it is discouraged. When I was stopping and starting, I was getting a different error message -11819, which corresponds to "AVErrorMediaServicesWereReset - The operation could not be completed because media services became unavailable.", which is much nicer than simply "unknown", but not necessarily any more helpful.
It successfully adds the AVCaptureStillImageOutput (i.e., does NOT emit the log message).
I am testing on an iPhone 3g (w/4.1) and iPhone 4.
This call is happening in the main thread, which is also where my original AVCaptureSession setup took place.
How can I avoid the error? How can I switch to the higher resolution to take the photo?
Thank you!
Since you're processing the video data coming out of the AVCaptureSession, I'm assuming you have an AVCaptureVideoDataOutput connected to it prior to calling sessionSetupForPhoto.
If so, can you elaborate on what you're doing in captureOutput:didOutputSampleBuffer:? Without being able to see more, I'm guessing there may be a problem with removing the old outputs and subsequently setting the photo quality preset.
Also, the output variable you're using as an iterator when you remove your outputs is hiding the still image output. Not a problem, but it makes the code a little harder to read.
There is no need to switch sessions. Just add AVCaptureStillImageOutput to your session on initialization and call the following when you are about to capture the image and use the CMSampleBufferRef accordingly:
captureStillImageAsynchronouslyFromConnection:videoConnection
completionHandler:^(CMSampleBufferRef imageDataSampleBuffer, NSError *error)
{
}

Game Center Finding a Match Programmatically

I just can't figure out how this works. What I am trying to do is let two players play a game if a third player joins it can instantly join the game, if the fourth and last player joins it can also instantly join the game. They can also leave the game at anytime for whatever reason, if that happens there should be a space open for another person or for the same person to reconnect. That's the idea.
Now what I got is the following. I authenticate the local player for obvious reasons. Then I search for a match like so:
if (matchRequest) [matchRequest release];
matchRequest = [[GKMatchRequest alloc] init];
matchRequest.minPlayers = 2;
matchRequest.maxPlayers = 4;
[[GKMatchmaker sharedMatchmaker] findMatchForRequest:matchRequest withCompletionHandler:^(GKMatch *match, NSError *error) {
if (error) {
// An error occured
} else {
if (matchCurrent) [matchCurrent release];
matchCurrent = [match retain];
matchCurrent.delegate = self;
}
}];
If I execute this part on three different devices, two of them will find each other and the third is still looking. So I figured after the find match for request has found the minimum amount of players it will be executed once. So what I needed was a method that used the matchCurrent that I retained to add more players. Luckely that method existed, but how would that work? When do you call it in this case? I decided to put it under a button so I could manually execute it when a match has been found.
What I discovered is that when I pressed it on the first device, finally the third device could find the match the first and second device were in. In fact the second and third device contained the playerIDs of every device involved. Which is a good thing. But there are two problems.
Which device should actually call the addPlayersToMatch method? And how can you restrict it to one device executing that method? Plus when should you call it?
Why, on the device calling that method, isn't the playerIDs updated?
[[GKMatchmaker sharedMatchmaker] addPlayersToMatch:matchCurrent matchRequest:matchRequest completionHandler:^(NSError *error) {
//matchCurrent.playerIDs is not updated?!
}];
Actually they are updated. When I see the playerIDs appear on the second and third device I manually update the matchCurrent.playerIDs on device one and suddenly it does recognize the player. However even the 'didChangeState' for player is not called when the new player is discovered on device one.
Your using the Apple iOS Game Center GKMatchmaker class. I'm assuming you are using a peer to peer connection, not hosted.
The GKMatch class gives the playerIDs array to you.
#property(nonatomic, readonly) NSArray *playerIDs
This is an ordered list, so you might be able to use it to select the first player call addPlayersToMatch.
Linked below is some documentation.
http://developer.apple.com/library/ios/#documentation/GameKit/Reference/GKMatchmaker_Ref/Reference/Reference.html
http://developer.apple.com/library/ios/#documentation/GameKit/Reference/GKMatch_Ref/Reference/Reference.html
http://developer.apple.com/library/ios/#documentation/NetworkingInternet/Conceptual/GameKit_Guide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40008304
Which device should actually call the
addPlayersToMatch method? And how can
you restrict it to one device
executing that method?
You could solve this problem by having the devices "draw straws". Each device generates a random number, then sends it to the others. The device with the largest number is the leader, and it is the one that must call addPlayersToMatch. If two devices pick the same number, throw out the numbers and start over.
I would suggest that you periodically (maybe once per second or two) poll for the status of other players, so you can detect if anyone has joined, or left for any reason. Unless the iphone architecture you are using already provides an function that handles that event.
It sounds like you may want to find some more documentation and/or sample code for the multi-player framework you are using.
I'm doing this with Unity via Prime31's GameCenterMultiplayerBinding. I'm not entirely sure how it maps to GameKit (the docs are sparse and don't give those details), but the names are very suggestive.
To be able to match 2 to 4 players into a match, I'm doing:
findMatchProgrammaticallyWithFilters(
minPlayers: 2,
maxPlayers: 4,
playerGroup: GetCurrentPlayerGroup(),
playerAttributes: 0);
I assume this maps to findMatchForRequest:withCompletionHandler.
After that succeeds, I call:
finishMatchmakingForMatch();
Which surely maps to finishMatchmakingForMatch. I found that calling findMatchForRequest or addPlayersToMatch would fail with "The requested operation has been canceled or disabled by the user" if I didn't call finishMatchmakingForMatch first.
addPlayersToCurrentMatchWithUpdatedMatchRequest(
minPlayers: 2,
maxPlayers: 4,
playerGroup: GetCurrentPlayerGroup(),
playerAttributes: 0,
playersToInvite: null);
addPlayersToMatch:matchRequest:completionHandler
After that succeeds, I call:
finishMatchmakingForMatch();
If I have space for more players, I loop and call addPlayersToMatch again.
I'd expect that since I need to call finishMatchmakingForMatch when I'm done
matchmaking, firing findMatchProgrammatically would keep looking until it
found maxPlayers, but it doesn't. It gives up after the first match. So we need
to call addPlayersToMatch.