Swift3: ABSearchElement crash - swift3

I have just updated my Swift 2 project to Swift 3 and I'm having a problem with a query on the AddressBook:
import Cocoa
import AddressBook
let firstName:String = "John"
let lastName:String = "Appleseed"
let addressBook = ABAddressBook.shared()
let firstNameSearch = ABPerson.searchElement(forProperty: kABFirstNameProperty,
label: nil,
key: nil,
value: firstName,
comparison: ABSearchComparison(kABEqualCaseInsensitive.rawValue))
let lastNameSearch = ABPerson.searchElement(forProperty: kABLastNameProperty,
label: nil,
key: nil,
value: lastName,
comparison: ABSearchComparison(kABEqualCaseInsensitive.rawValue))
let comparisons = [firstNameSearch, lastNameSearch]
let andComparison = ABSearchElement(forConjunction: CFIndex(kABSearchAnd.rawValue), children: comparisons)
let peopleFound = addressBook?.records(matching: andComparison) as! [ABRecord]
if peopleFound.count > 0
{
let contact = peopleFound[0]
}
It's crashing with this error
2016-09-15 12:59:02.657 com.apple.dt.Xcode.PlaygroundStub-macosx[37940:8204350] -[_SwiftValue searchRecordClasses]: unrecognized selector sent to instance 0x7fc098ec9600
2016-09-15 12:59:02.658 com.apple.dt.Xcode.PlaygroundStub-macosx[37940:8204350] An uncaught exception was raised
2016-09-15 12:59:02.658 com.apple.dt.Xcode.PlaygroundStub-macosx[37940:8204350] -[_SwiftValue searchRecordClasses]: unrecognized selector sent to instance 0x7fc098ec9600
when executing this line:
let andComparison = ABSearchElement(forConjunction: CFIndex(kABSearchAnd.rawValue), children: comparisons)
Does anyone know what the updated Swift 3 code should be?

That _SwiftValue is often found when passing some Optional to Any.
Try changing your comparisons like this:
let comparisons = [firstNameSearch!, lastNameSearch!]

Related

How do I access my data in a PKPushPayload?

XCode 7, Swift 2. (don't even start on me about that, it's not my favorite set of constraints either)
So I'm sending data using node-apn (BIG thanks to those folks!). I'm using the (pushkit option) *.voip topic and I got all that working. I can see the notification is received on my device (big shout out to libimobiledevice).
In composing the note on my server i'm doing
var note = new apn.Notification();
note.topic = 'mine.voip';
note.payload = {
message: 'text',
somethingElse: 'this other one '
payload: {
k1: v1,
k2: {
k3: v2
}
}
};
How am I supposed to get at my payload object? Following some (3rd party) pushkit examples (maybe it was 1? that showed like
func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) {
let payloadDict = payload.dictionaryPayload["aps"] as? Dictionary<String, String>
let message = payloadDict?["alert"]
}
I tried to mimic it like
let myWeirdPayload = payload.dictionaryPayload["payload"] as? Dictionary<String, String>
or even
let myWeirdPayload = payload.dictionaryPayload["payload"] as? Dictionary<String, Any>
but those don't work (I get nil).
How am I supposed to do this?
Here's how I log it in Obj-C:
NSLog(#"pushRegistry:didReceiveIncomingPushWithPayload:forType:withCompletionHandler:%#",
payload.dictionaryPayload);
Let me try to make this clear by explaining the relation between PKPushPayload and its NSDictionary property with the data you are looking for.
For the func pushRegistry(registry: PKPushRegistry!, didReceiveIncomingPushWithPayload payload: PKPushPayload!, forType type: String!) you have the payload argument which is a PKPushPayload.
The data you are looking for are stored in the _dictionaryPayload which is a NSDictionary and it is a property of the payload argument.
So to access the data you can do:
let payloadDictionary = payload.dictionaryPayload as NSDictionary
let myData = payloadDictionary.value(forKey: "myData_unique_key")

How we can pass default null value in parameter list of dictionary [String:String] while posting a request to server ? Swift3

In some case i have to post null values to server either as a default value or as a parameter's value.I tried many ways but it didnt work.I'm using Alamofire for posting a request.Please help.
Method-1
var empty : String = ""
let parameters = ["User-Id":userId,"search_cat": formattedArray ?? empty,"date1":ab ?? empty,"date2" : bc ?? empty,"docname" : empty
] as! [String : String]
Method-2
let parameters = ["User-Id":userId,"search_cat": formattedArray ?? "","date1":ab ?? "","date2" : bc ?? "","docname" : ""
] as! [String : String]
Method-3
var nullvalue : String = ""
if formattedArray == nil
{
formattedArray = ""
print(formattedArray)
}
if ab == nil
{
ab = ""
print(ab)
}
if bc == nil
{
bc = ""
print(bc)
}
if nullvalue == nil
{
nullvalue = ""
}
parameters = ["User-Id":userId,"search_cat": formattedArray,"date1":ab ,"date2" : bc ,"docname" : nullvalue ]
as! [String : String]
Method - 4 According to answer i changed parameterlist dictionary to [String:AnyObject] but still it's not working.And giving me the error.
var ab:String?
var bc : String?
var formattedArray: String?
parameters = ["User-Id":userId ,"search_cat": formattedArray ?? NSNull() ,
"date1":ab ?? NSNull() ,"date2" : bc ?? NSNull(),
"docname" : NSNull()] as! [String : AnyObject]
Method-4 giving me Error while trying to set formattedArray ?? NSNull() :
Cannot convert value of type 'NSNull' to expected argument type 'String'
with rest of the parameters its working fine.Please help.
UPDATED : is this that you want?
class RequestParameter : NSObject{
var formattedArray : String!
var date1 : String!
var date2 : String!
var docName : String!
var userId : String! // or whatever if hardCoded
func param() -> NSDictionary{
var param : [String : String] = [:]
param["User-Id"] = userId
param["search_cat"] = formattedArray
param["date1"] = date1
param["date2"] = date2
param["docname"] = docName
return param as! NSDictionary
}
}
You can call these parameters where ever required. like
var reqParam = RequestParameter()
reqParam.param()
I am really unaware of your Request parameter type. For eg. should it look like date1 = nil or something else.
This is all I could answer you. If wrong maybe someone might ans better.
Good Luck!!
I actually had the same issue a couple of days ago and solved it using NSNull().
When converting my class I want to send the videoUrl property regardless of it containing a value, so that the backend can update it in the DB.
dict["videoUrl"] = videoUrl ?? NSNull()
This will set the key "videoUrl" with the value of the property videoUrl, or if nil, an instance of NSNull().
Express.js then reads this as undefined and inserts a null value to the database.
EDIT: I saw one of your comments below. When using a Dictionary of type [String:String], you will never be able to pass a nil value.

Migration Alamofire swift2 from swift 3

Previously in my APP when I was making a call to the server if there were any errors I did the following:
Alamofire.request(mutableURLRequest).responseJSON{
response in if let JSON = response.result.value{
if JSON.count != 0{
let errorList = JSON["responseErrorsList"] as? NSArray
for error in errorList!{
let erro: String = error as! String
switch erro{
case "PersonRequired":
With the migration from swift 2 to swift 4 I am having problems because theList errors comes to nil however the result of JSON is as follows:
["Rate": , "Level": , "Code": , "ID": 0, "Zone": , "Address": , "ErrorsListServer": <__NSSingleObjectArrayI 0x17400ba90>( InvalidCode ) , "SubZone": ]
Does anyone know how I can access the "ErrorsListServer" field and fetch the errors that in this case is "InvalidCode".
What I have implemented and is not working for is the following:
if let JSON = response.result.value as? [String: Any]{
if (JSON as AnyObject).count != 0{
let errorList = JSON["responseErrorsList"] as? [[String: Any]]
From your JSON response, you need to access key ErrorsListServer and it is Array of String not Array of Dictionary so you need to cast it to [String]. Also you can reduce your code with single if let statement like this way.
if let JSON = response.result.value as? [String: Any],
let errorList = JSON["ErrorsListServer"] as? [String] {
for error in errorList {
print(error)
}
}

What is the form for a throwing raiseKEY validation func in Swift 3?

I'm going through the Hillegass book, 5th Edition, 10th Chapter, RaiseMan example.
He indicates this Swift 2 code:
class Employee: NSObject {
var name: String? = "New Employee"
var raise: Float = 0.05
}
//
//func validateRaise(raiseNumberPointer: AutoreleasingUnsafeMutablePointer<NSNumber?>, error outError: NSErrorPointer) -> Bool {
//
// let raiseNumber = raiseNumberPointer.pointee
// if raiseNumber == nil {
// let domain = "UserInputValidationErrorDomain"
// let code = 0
// let userInfo = [NSLocalizedDescriptionKey : "An employee's raise must be a number."]
// outError?.pointee = NSError(domain: domain, code: code, userInfo: userInfo)
// return false
// }
//
// return true
//}
which doesn't work in Xcode 8.1, Swift 3.0.1, of course. So I tried:
```
enum EmployeeError: Error {
case badRaise
}
func validateRaise(raiseNumberPointer: AutoreleasingUnsafeMutablePointer) throws {
let i = 1
do {
guard let raiseNumber = try raiseNumberPointer.pointee else {
throw EmployeeError.badRaise
}
let domain = "UserInputValidationErrorDomain"
let code = 0
let userInfo = [NSLocalizedDescriptionKey : "An employee's raise must be a number."]
}
}
```
but setting a breakpoint showed me that this code is never called. In IB, obviously, I went to the appropriate NSTextField and checked off validate immediately, as instructed. this is the error I got:
```
2016-11-02 07:46:31.163900 RaiseMan[19240:1489479] [General] An uncaught exception was raised
2016-11-02 07:46:31.163986 RaiseMan[19240:1489479] [General] [ setNilValueForKey]: could not set nil as the value for the key raise.
```
if someone knows the right syntax, that would be very helpful. thanks.
Another user found this on the Big Nerd Ranch site and sent it to me on Slack.
https://forums.bignerdranch.com/t/validateraise-function-changes-in-swift-3-exception-is-not-being-handled/9279

I'm trying to read json data and it is returning "false"

Here is my code that is returning a false instead of the json array count.
I must comment that at one point it was working and then it stopped. Please help.
let task = NSURLSession.sharedSession().dataTaskWithURL(url!, completionHandler: { (data, response, error) -> Void in
let urlError = false
if error == nil {
let urlContent = NSString(data: data!, encoding: NSUTF8StringEncoding) as NSString!
let data: NSData = urlContent.dataUsingEncoding(NSUTF8StringEncoding)!
print("data here\(data)”) // I see a lot of data in the logs with this print
do {
let jsonObject = try (NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.MutableContainers) as? NSArray)!
print(“here is the array count\(jsonObject.count)”) // it never prints this to the logs. What I get is “false"
…The rest of the code...