EKParcipant URL访问崩溃的解决方法?

时间:2016-11-25 11:35:26

标签: swift swift3

我的一些用户已经向我发送了这行代码中标识EXC_BREAKPOINT (SIGTRAP)错误的日志。我一直试图让它安全但EKParticipant的所有属性都是非可选的,所以与nil相比只是给了我一个警告,说它永远是真的。如果有什么东西在这里我应该怎么处理呢?

错误行

let participantEmail : String? = participant.url.absoluteString.lowercased().replacingOccurrences(of: "mailto:", with: "")

Apple错误说明

  

跟踪陷阱[EXC_BREAKPOINT // SIGTRAP]

     

与异常退出类似,此异常旨在提供   附加调试器有机会在特定的情况下中断进程   指出它的执行。您可以从自己的触发器中触发此异常   代码使用__builtin_trap()函数。如果没有附加调试器,   该过程终止并生成崩溃报告。低等级   库(例如,libdispatch)将在遇到a时捕获进程   致命错误。有关错误的其他信息,请参阅   崩溃报告的附加诊断信息部分,或   在设备的控制台中。 Swift代码将以此异常终止   如果在运行时遇到意外情况,则输入类型,例如:       具有nil值的非可选类型       失败的强制类型转换查看Backtraces以确定遇到意外情况的位置。额外   信息可能也已记录到设备的控制台。您   应修改崩溃位置的代码以正常处理   运行时失败。例如,使用Optional Binding而不是   强行打开一个可选项。"

完整方法

    /**
Parses participants for a given event.
 Goes through the EKEvents attendees array to build Attendee objects used to model a participant.

 - parameter event: The calendar event we'll be finding the participants for.
 - returns: An array of Attendee objects with the participants name, email, required/optional status and whether they've accepted their invitation to the event.
 */
private static func parseParticipantsIn(event: EKEvent) -> [Attendee] {
var participants = [Attendee]()

if let attendees = event.attendees, event.attendees?.isEmpty == false {
    for participant in attendees {
        let participantName : String? = parse(EKParticipantName: participant)
            let participantEmail : String? = participant.url.absoluteString.lowercased().replacingOccurrences(of: "mailto:", with: "")

            let isRequiredParticipant : Bool = participant.participantRole == EKParticipantRole.required
            let hasAccepted : Bool = participant.participantStatus == EKParticipantStatus.accepted

             guard (participantName != nil && participantEmail !=  nil)
                else
            {
                log.error("Participant could not be parsed")
                continue
            }
            let attendee = Attendee(name: participantName!, email: participantEmail!, required: isRequiredParticipant, hasAccepted: hasAccepted)
            participants.append(attendee)
        }
    }
    return participants
}

5 个答案:

答案 0 :(得分:2)

这似乎是EKParticipant.url属性的问题。如果您的参与者中包含以下电子邮件字段,则任何尝试访问EKParticipant.url都会导致崩溃。

"Bill Gates" <billgates@google.com>

我猜引号过早地结束了字符串。从EKParticipant.description访问时很好,所以我打算从那里解析它。

答案 1 :(得分:2)

这是一个荒谬的问题,而Deco则精确地指出了它。我使用了一种不同的方法来解决它:因为我已经在混合代码库(obj-c和Swift)中工作,所以我在我的一个obj-c类上创建了一个类方法,它接受一个EKParticipant和将其URL作为字符串返回。然后,在Swift中,我调用该类方法来获取URL而不是直接访问属性(并崩溃)。它很糟糕,但比崩溃更好,并使我免于解析描述。

答案 2 :(得分:2)

这是一个相当古老的问题,但我自己也遇到了这个问题。我的解决方案是回退到ObjC以解决它。

只需将此ObjC函数添加到swift桥接头文件中,您就可以在swift中使用它们。

int main(void)
{
  int user_input = 0, elements = 0;
  printf("How many int elements will you enter?\n");
  scanf("%d", &elements);

  int* dynamic_array = (int *)malloc(sizeof(int)* elements);
  if(dynamic_array == NULL) {
     perror(" Out of memory ");
     return 0;
  }

  for (int i = 0; i < elements; i++)
  {
    printf("Element %d?\n", i + 1);
    scanf("%d", &dynamic_array[i]);
  }

  for (int printf_number = 0; printf_number < elements; printf_number++)
  {
    printf("Element %d: %d\n", printf_number+1, dynamic_array[printf_number]);
  }

  free(dynamic_array);
  dynamic_array = 0;
  return 0;
}

使用示例:

static inline BOOL
participantHasNonNilURL (EKParticipant* _Nonnull  participant) {
    return participant.URL != nil;
}

static inline NSURL* _Nullable
participantURL(EKParticipant* _Nonnull  participant) {
    if (participant.URL != nil) {
        return participant.URL;
    }else {
        return nil;
    }
}

答案 3 :(得分:1)

这在 macOS 11.2 上仍然是一个问题...我有 reported 给 Apple。我鼓励其他遇到此问题的人也这样做。

唯一对我有用的 Swift 解决方法是:

extension EKParticipant {
    public var safeURL: URL? {
        perform(#selector(getter: EKParticipant.url))?.takeUnretainedValue() as? NSURL? as? URL
    }
}

答案 4 :(得分:0)

验证添加错误,请查看以下有关如何使用防护的回复。

if let attendees = event.attendees, event.attendees?.isEmpty == false {
    for participant in attendees {
        guard let participantName : String? = parse(EKParticipantName: participant) else{ 
              log.error("error in participant name")
              return
          }
        guard let participantEmail : String? = participant.url.absoluteString.lowercased().replacingOccurrences(of: "mailto:", with: "") else{ 
              log.error("error in participant email")
              return
          }

       let isRequiredParticipant : Bool = participant.participantRole == EKParticipantRole.required
       let hasAccepted : Bool = participant.participantStatus == EKParticipantStatus.accepted

       /* guard validation is not required here */
       if (participantName != nil && participantEmail !=  nil){
            let attendee = Attendee(name: participantName!, email: participantEmail!, required: isRequiredParticipant, hasAccepted: hasAccepted)
            participants.append(attendee)
       }
    }
}
return participants