-1
var currentContact = CNLabeledValue<NSCopying & NSSecureCoding>()

I want to create a variable which will store the value from the contact which can be either a phone number or an email address

var currentContact = CNLabeledValue<NSCopying & NSSecureCoding>()
currentContact = self.itemsInAcontact[section][0] as! CNLabeledValue


if ((currentContact.value as? CNPhoneNumber) != nil){
    phoneNumber = currentContact.value as! CNPhoneNumber

    if let y = phoneNumber?.value(forKey: "initialCountryCode"){
        cell.nameLabel!.text = "\(phoneNumber!.value(forKey: "initialCountryCode") as! String)\(phoneNumber!.stringValue)"
    }else{
        cell.nameLabel!.text = "\(phoneNumber!.stringValue)"
    }
}else{
    cell.nameLabel!.text = currentContact.value as! String
}

Here i am trying to display the contact number or email address available in a no name type contact inside the cell of a tableview, but I'm getting error on declaration of var currenctContact

The error message: "'NSCopying & NSSecureCoding' cannot be used as a type conforming to protocol 'NSSecureCoding' because 'NSSecureCoding' has static requirements".

Abhijit_R
  • 13
  • 8
  • You need to give the full error message which is "'NSCopying & NSSecureCoding' cannot be used as a type conforming to protocol 'NSSecureCoding' because 'NSSecureCoding' has static requirements". – Larme Apr 12 '19 at 10:31

2 Answers2

4

LabeledValue is a generic. Two different LabeledValue types (that is, the same generic resolved in two different ways, CNLabeledValue<NSString> and CNLabeledValue<CNPhoneNumber>) are different types and cannot be stored in a common property. This is no different from the fact that [Int] and [String] are two different types even though they are both arrays.

The only way you can store two different LabeledValue types in a single property is to type that property as AnyObject. Thus, this works:

var currentContact : AnyObject? = nil

let phoneNumber = CNPhoneNumber(stringValue: "1234567890")
let labelled = CNLabeledValue(label: "yoho", value: phoneNumber)
currentContact = labelled

let email = CNLabeledValue(label: "hoha", value: "mickey@mouse.com" as NSString)
currentContact = email

However, I don’t recommend doing that. Instead, since all you really need is a string, make your currentContact a labeled value wrapping an NSString:

var currentContact : CNLabeledValue<NSString>? = nil

You can store an email CNLabeledValue directly into that. For a phone number, form a new labeled value from the phone number’s string value:

currentContact = CNLabeledValue(
    label:phone.label, value:phone.value.stringValue as NSString)
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • actually here i have to distinguish 1) !$_, value=anna-haro@mac.com> from 2) !$_, value=> and represent appropriately, if i store a String in my model, it works fine for emails but not for phone numbers – Abhijit_R Apr 15 '19 at 08:50
  • My answer still stands. You cannot store two different types in one variable. If you need to store emails and phone numbers that’s at least two variables, not just one. – matt Apr 15 '19 at 11:55
  • You can transform the phone number into a `CNLabeledValue`. That gives it a common type with the email labeled value, and you can store either of them in the same property. I’ve edited to demonstrate. – matt Apr 15 '19 at 15:17
0

Looks like Apple changed something on NSSecureCoding in XCode 10.2 but I couldn't find any details yet.

So, for now, you should change from NSCopying & NSSecureCoding to NSString

var currentContact = CNLabeledValue<NSString>()
ggoncalves
  • 41
  • 3
  • actually here i can get either: 1) !$_, value=anna-haro@mac.com> or 2) !$_, value=> if i use the change u have suggested i can get email values correctly but in case of a CNPhoneNumber value it crashes – Abhijit_R Apr 15 '19 at 08:45