Error in CallKit CallDirectory Extension - swift

im implementing callKit in my iOS project, im using the callDirectory extension to block and identify Numbers, the block part works perfectly , the only problem is when i try to add numbers to be identified:
private func retrievePhoneNumbersToIdentifyAndLabels() -> (phoneNumbers: [String], labels: [String])? {
// retrieve list of phone numbers to identify, and their labels
interDefaults?.synchronize()
if let numbers = interDefaults!.string(forKey: "ident-numbers"){
if let identities = interDefaults!.string(forKey: "ident-identities"){
let formattedNumbers = numbers.characters.split{$0 == "*"}.map(String.init)
let formattedIdent = identities.characters.split{$0 == "*"}.map(String.init)
return (formattedNumbers, formattedIdent)
}
}
return ([""], [""])
}
When i try to relaod the extension it fails with error : Error Domain=com.apple.CallKit.error.calldirectorymanager Code=3 "(null)"
with some testing i figured out that by replacing the formattedIdent with an array of 1 element EXP: ["Spamm Caller"] the extension works perfectly and shows no error but when i use an array with more than one element the same error shows up.
im i doing something wrong ?? thanks in advance

I had similar issue but the mistake I did was with error code 4. So I digged in the CXErrors and found this enum.
public enum Code : Int {
public typealias _ErrorType = CXErrorCodeCallDirectoryManagerError
case unknown
case noExtensionFound
case loadingInterrupted
case entriesOutOfOrder
case duplicateEntries
case maximumEntriesExceeded
case extensionDisabled
#available(iOS 10.3, *)
case currentlyLoading
#available(iOS 11.0, *)
case unexpectedIncrementalRemoval
}
So basically unknown == Code 0 and the other options increment with one. This is the full list of errors you can receive while your extension tries to handle new data up to this date.

The error codes from CallDirectory are defined in the header <CallKit/CXError.h>, which includes:
CXErrorCodeCallDirectoryManagerErrorEntriesOutOfOrder = 3,
This particular error is returned when the phone number(s) provided are out of order. Numbers must be provided in numerically ascending order.

I was getting error 3 even though I know that my numbers are ordered correctly. What fixed it for me was commenting out the example code in the private function that is in CallDirectoryHandler file.
I'm only using caller id at this time, but if I were using blocking also, well, I'd get rid of that sample code as well.

Related

Swift Dictionaries with enum as Identifier not auto completing in completion block

I have a function that returns a completion. The completion has as in parameter a custom class with a dictionary that uses an enum as an identifier.
The problem I am facing is that Xcode does not recognises the type of the variable and does not auto complete when I use it inside of completion block.
My code looks like that
Function
func testFunc (completion:(PrxServiceResponseCallback) ->()){
let responseCallback = PrxServiceResponseCallback()
completion(responseCallback)
}
Class
class PrxServiceResponseCallback:NSObject{
var success = false
var resultCode:Int32 = 0
var response:[PrxResponseAttributes:Any] = [PrxResponseAttributes:Any]()
}
enum PrxResponseAttributes{
case sourceProtocolInfoArray
case sinkProtocolInfoArray
case connectionIDsArray
case connectionInfo
}
Calling the function
testFunc { (testResonse) in
testResonse.response[.]//Not Auto completing
}
The whole idea of making a dictionary with an enum as identifier was to make easier which attributes the dictionary returns but, If I can't auto complete, the idea is more pointless.
Any ideas?
Xcode doesn't give you autocomplete doesn't mean that your code doesn't compile. It just means that Xcode is too stupid to figure things out. I have encountered such situations many times before. It seems to always happen inside closures.
You can just ignore the fact that no autocomplete shows up and type the case name yourself:
testResonse.response[.sourceProtocolInfoArray]
It will compile.
You can also consider creating a struct instead of storing the values in a dictionary. Here's a sample struct (I guessed the types):
struct Response {
let sourceProtocolInfo: [String]
let sinkProtocolInfo: [String]
let connectionIDs: [Int]
let connectionInfo: String
}
If you use var response:[UIColor:Any] = [UIColor:Any]()
it is still not giving auto complete so it is not your issue and you can not do much on it .
If you need auto complete then use PrxResponseAttributes with . (dot)
you can do it like
testResonse.response[PrxResponseAttributes.sourceProtocolInfoArray]
EDIT
Note: It is only happening with implemented closure if you add one property in your PrxServiceResponseCallback class like
var anyValue:Any? {
return response[.connectionInfo] // it is showing completion
}

Enum initialized with a non-existent rawValue does not fail and return nil

I have the following code in a playground (Xcode 9.0.1):
import MapKit
enum Test: UInt {
case first
case second
case third
}
let test = Test(rawValue: 4) as Any
print(test) // nil
let type = MKMapType(rawValue: 999)
print(type == nil) // false
print(type!.rawValue) // 999
MKMapType is defined as
enum MKMapType : UInt
As the maximum value of a MKMapType is 5, I expect the initializer of the enum to fail and return nil. Instead it returns 999. Am I missing some ObjC/Swift bridging here or could this be a bug?
I filed a bug with Apple and this is the reply I received:
"Engineering has determined that this issue behaves as intended based on the following information:
Because C enums may have values added in future releases, or even have "private case" values used by the framework that are not included in the headers, there's no way to check whether a value provided in Swift is actually valid or invalid. Therefore, init(rawValue:) is obliged to produce a value just as a C cast would. There are discussions in the Swift Open Source project on how to improve this situation in later versions of Swift, but the initializer for MKMapType still won't return nil."
Thanks to Apple Engineering for this explanation.

Swift is using the wrong subscript overload. How can I get it to use the right one?

I'm writing UI testing code using XCTest. Here is my test method:
func testLandingUI() {
let app = XCUIApplication()
let headerExpectedMessage = "Title"
let headerLabel = app.staticTexts[headerExpectedMessage]
XCTAssert(headerLabel.exists)
}
I'm getting this error:
ExampleUITests.swift:38:19: error: value of type 'Any?' has no member 'exists'
XCTAssert(headerLabel.exists)
^~~~~~~~~~~ ~~~~~~
What's strange about this error is that I expected headerLabel to be of type XCUIElement, not Any?.
XCUIApplication.staticTexts is an XCUIElementQuery, which has a subscript method declared thusly:
open class XCUIElementQuery : NSObject, XCUIElementTypeQueryProvider {
...
open subscript(key: String) -> XCUIElement { get }
...
}
What I believe is happening is the subscript method in XCUIElementQuery is not being selected by Swift's overload resolution. Instead, it's selecting this category on NSObject:
#interface NSObject (MyCategory)
- (id)objectForKeyedSubscript:(NSString*)key;
- (void)setObject:(id)obj forKeyedSubscript:(NSString*)key;
#end
I verified that if I remove that category from my project, the error goes away. Assume that removing that category is not possible (because it's not). Is there any way to get Swift to use the correct subscript method?
Minimal test case that shows the problem: https://www.dropbox.com/s/f0fm5ennco7t2ua/SubscriptCategoryTest.zip?dl=1
(note that the error is in the UI tests, so press command-shift-U to see the error)
EDIT: It looks like the problem only shows up if the category defines setObject:forKeyedSubscript:. Interestingly, I get a slightly different error if both getter and setter are defined vs. just the setter.
Since the compiler is confused, you need to help it....
Given this example:
let example1: Any? = "1"
let example2: Any = "2"
You have two issues (it looks like you have an optional...)
if example1.exists { // won't work - I got your error message
}
if (example2 as AnyObject).exists { // works with a cast
}
I believe if you correct identify the type of the variable it will solve your problem. It is matching the NSObject category only because it didn't match something more specific.

Command failed due to signal: Segmentation fault: 11 | Xcode 7.2

I was asked to migrate a rather large app to Swift 2. The compiler keeps throwing segmentation fault: 11 errors for one function, present in different modules of the app's logic (only difference being variables used):
func loadMoreContent() {
if let collection = self.ratingsCollection where collection.identifier != 0,
let totalEntries = collection.totalEntries,
let objects = self.ratings?.count where objects < totalEntries {
self.ratingsCollection = nil
collection.nextPage().onSuccess { (value) in
if let collection = value as? Collection<Rating> {
self.ratingsCollection = collection
} else {
self.ratingsCollection = Collection<Rating>(identifier: 0)
}
}.onFailure { error in
self.ratingsCollection = Collection<Rating>(identifier: 0)
}
}
}
Here are the errors themselves:
1. While type-checking 'loadMoreContent' at (path redacted).swift:46:3
2. While type-checking expression at [(path redacted).swift:54:9 - line:64:9]
RangeText="collection.nextPage().onSuccess { (value) in
if let collection = value as? Collection<Rating> {
self.ratingsCollection = collection
} else {
self.ratingsCollection = Collection<Rating>(identifier: 0)
}
}.onFailure { error in
self.ratingsCollection = Collection<Rating>(identifier: 0)
}"
3. While loading members for declaration 0x7fdda42ea2b0 at <invalid loc>
4. While deserializing 'producer' (FuncDecl #340)
Does anyone have any idea what can be wrong with this function at first glance? I should add it compiles with no changes in Xcode 6 / Swift 1.2.
This is a hair pulling error especially common in XCode7.
Occasionally the usual XCode stupid bug protocol (clean, XCode Restart, clean, build) fixes it. However, often it is due to one or more offending lines of code. This doesn't necessarily mean there is a bug in the code, either!
So, before restarting, it is sometimes useful to undo recent changes sequentially and trying to build as you go along. If any of your dependencies or frameworks have been updated since your last successful build, these could be a likely candidate.
There are a couple things that seem to produce this error fairly regularly. So please add to this list concisely if you can isolate specific issues that CONSISTENTLY cause errors for you:
1) String concatenation using the plus operator in calls to methods that use autoclosures (found in calls to XCGLogger):
public func myFunc(#autoclosure closure: () -> String?){
// do something
}
someInstance.myFunc("Hi " + nameStr + "!")
2) failure to call super.init() from subclass especially when super class is using a default initializer (you haven't explicitly created your own init)
3) Accidentally using a single equals sign to test for equality (using = instead of == ) especially in complex statement such as in this answer.

Swift Compiler Error when accessing array - Exit code 254

I am quite new to swift and got a pretty weird compiler error:
Command
/Applications/Xcode6-Beta5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc
failed with exit code 254
The Error occours when I ad the following lines to my code:
var response = HoopsClient.instance().collections["posts"]
response = response["_id"]
when I remove the second line everything compiles fine. I don't get it ^^
edit: The reason is probably that "response" is of type "AnyObject" according to the compiler... but shouldn't that be detected by xcode or give me a runtime error instead of this compiler error?
Try casting response as the type you're expecting. From what you're trying to do, instance().collections I would assume that it should return some type of dictionary.
var response = HoopsClient.instance().collections["posts"] as NSDictionary
That way, response now can handle subscripts so you could now (in theory) do:
response = response["_id"]
However
The error you get is regarding bad access to an array. This makes me think that instance().collections actually returns an array of some sort, containing Post objects.
Arrays in Swift can only handle Integer subscripts. If you want to access the information of a Post in the array, you can do something like this:
for post: Post in response {
println(post._id)
}
I know this is a long shot, but hope it helps.
Swift tends to throw error when it cant infer the type of an object, what you could probably do is add a conditional cast as follows
Im assuming that HoopsClient.instance().collections["posts"] is either a Dictionary or an Array
var response = HoopsClient.instance().collections["posts"]
if response is NSArray {
let item = response.objectAtIndex(0)
let reponseId: Post = item
}
if response is NSDictionary {
let item = response.objectForKet("_id")
let reponseId: Post = item
}
Any way, in my experience you should try to cast your variables when assigning from types that return AnyObject, xcode doesn't handle very well type inferring and when it's unable to infer the type the interface starts to throw error, like text editor uncoloring the code.