阿拉伯语的主题标签使应用程序崩溃 [英] Hashtags in Arabic language crashes the app

查看:92
本文介绍了阿拉伯语的主题标签使应用程序崩溃的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个主题标签解析器UITextView扩展,它将带有#"的任何单词转换为可点击的蓝色链接.除点击阿拉伯主题标签外,它工作正常.

I have a hashtags resolver UITextView extension that turns any word with "#" before it to a tappable blue link. It is working fine except when tapping on Arabic hashtags.

extension UITextView {

func resolveHashAndMentionTags(){

    // turn string in to NSString
    let nsText:NSString = self.text as NSString

    // this needs to be an array of NSString.  String does not work.
    let words:[NSString] = nsText.components(separatedBy: " ") as [NSString]

    // you can't set the font size in the storyboard anymore, since it gets overridden here.
    let attrs = [
        NSAttributedStringKey.font : UIFont(name: "Avenir-Light", size: 14.0)!//UIFont.systemFont(ofSize: 13.0)

    ]

    // you can staple URLs onto attributed strings
    let attrString = NSMutableAttributedString(string: nsText as String, attributes:attrs)

    // tag each word if it has a hashtag or mention
    for word in words {

        // found a word that is prepended by a hashtag!
        if word.hasPrefix("#") {

            // a range is the character position, followed by how many characters are in the word.
            // we need this because we staple the "href" to this range.
            let matchRange:NSRange = nsText.range(of: word as String)

            // convert the word from NSString to String
            // this allows us to call "dropFirst" to remove the hashtag
            var stringifiedWord:String = word as String

            // drop the hashtag
            stringifiedWord = String(stringifiedWord.dropFirst())

                print(stringifiedWord)
                attrString.addAttribute(NSAttributedStringKey.link, value: "hash://\(stringifiedWord)", range: matchRange)
         //   }

        } else if word.hasPrefix("@") {

            // a range is the character position, followed by how many characters are in the word.
            // we need this because we staple the "href" to this range.
            let matchRange:NSRange = nsText.range(of: word as String)

            // convert the word from NSString to String
            // this allows us to call "dropFirst" to remove the mention@
            var stringifiedWord:String = word as String

            // drop the hashtag
            stringifiedWord = String(stringifiedWord.dropFirst())


            attrString.addAttribute(NSAttributedStringKey.link, value: "mention://\(stringifiedWord)", range: matchRange)
           // }
        }
    }

    // we're used to textView.text
    // but here we use textView.attributedText
    // again, this will also wipe out any fonts and colors from the storyboard,
    // so remember to re-add them in the attrs dictionary above
    self.attributedText = attrString
}

然后在我的帖子单元格中,调用 UITextViewDelegate 函数.

Then in my posts cell i call the UITextViewDelegate function.

func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool {

    let path = URL.absoluteString
    switch URL.scheme! {
    case "hash" :
        let hash = path.removingPercentEncoding?.components(separatedBy: "://").last
        print(hash!) // ---> Retriving tapped on hash name correctly
        delegate?.hashTableViewCell(self, shouldSelectTag: hash!)
    case "mention" :
        let mention = path.removingPercentEncoding?.components(separatedBy: "://").last
        print(mention!) // ---> Retriving tapped on mention name correctly
        delegate?.mentionTableViewCell(self, shouldSelectTag: mention!, userId: nil)
    default:
        print("Just a regular link \(path.removingPercentEncoding!)")
    }
    return true
}

就像我上面提到的代码一样,它对于英文字母也可以正常工作,但是当点击阿拉伯文的标签或提及它在 AppDelegate 中崩溃时.

As i mentioned above the code it is working fine for english letters but when tapping on an arabic hashtag or mention it crashes in the AppDelegate.

线程1:EXC_BREAKPOINT(代码= 1,子代码= 0x1030fcb94)

Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1030fcb94)

我尝试使用断点进行调试,以了解错误的确切位置,但实际上我发现,即使在进入 UITextViewDelegate 函数之前,它仍然崩溃.所以现在我完全不知道错误可能在哪里.

I tried to debug with break points to know where the error is exactly but actually i found out that it is crashing even before entering the UITextViewDelegate function. So now i have no clue at all where the error could be exactly.

也许会出现某种问题,将阿拉伯字母用作 UITextView 中的链接?

Maybe there could be some kind of an issue with arabic letters being used as a link in a UITextView?

这是堆栈跟踪.

  • 线程#1,队列='com.apple.main-thread',停止原因= EXC_BREAKPOINT(代码= 1,子代码= 0x1030fcb94)框架#0:0x00000001030fcb94 libswiftFoundation.dylib 功能签名专门化< Arg [0] =拥有保证,Arg [1] =无效>静态Foundation.URL._unconditionallyBridgeFromObjectiveC(Swift.Optional< __ ObjC.NSURL>)->Foundation.URL + 288框架#1:0x0000000103045f24 libswiftFoundation.dylib 静态Foundation.URL._unconditionallyBridgeFromObjectiveC(Swift.Optional< __ ObjC.NSURL>)-> Foundation.URL + 20框架#2:0x0000000101199c68 OOL @objc PostTableViewCell.textView(_:shouldInteractWith:in :)在PostTableViewCell.swift:0框架#3:0x000000018e1e397c UIKit -[_ UITextViewInteractableLink allowInteraction:] + 360框架4:0x000000018e1e2698 UIKit -[_ UITextViewInteractableItem handleTap] + 40框架#5:0x000000018db64548 UIKit -[UITextGestureClusterLinkInteract smallDelayRecognizer:] + 296框架6:0x000000018db7ccd0 UIKit <代码>-[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 64框架7:0x000000018db812c4 UIKit _UIGestureRecognizerSendTargetActions + 124框架8:0x000000018d659aa8 UIKit _UIGestureRecognizerSendActions + 320框架#9:0x000000018d510c38 UIKit -[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 732框架#10:0x000000018db6ab34 UIKit _UIGestureEnvironmentUpdate + 1084框架#11:0x000000018db6a6a4 UIKit -[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 404框架#12:0x000000018db69800 UIKit -[UIGestureEnvironment _updateGesturesForEvent:window:] + 276框架#13:0x000000018d50ef44 UIKit -[UIWindow sendEvent:] + 3180框架14:0x000000018d4dff64 UIKit -[UIApplication sendEvent:] + 340框架#15:0x000000018de3531c UIKit __ dispatchPreprocessedEventFromEventQueue + 2364框架#16:0x000000018de378a8 UIKit __ handleEventQueueInternal + 4760框架#17:0x000000018de307c0 UIKit __ handleHIDEventFetcherDrain + 152框架#18:0x0000000183fa697c CoreFoundation <代码> __ CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24框架#19:0x0000000183fa68fc CoreFoundation __ CFRunLoopDoSource0 + 88帧#20:0x0000000183fa6184 CoreFoundation <代码> __ CFRunLoopDoSources0 + 204框架#21:0x0000000183fa3d5c CoreFoundation __ CFRunLoopRun + 1048框架#22:0x0000000183ec3e58 CoreFoundation CFRunLoopRunSpecific + 436框架#23:0x0000000185d70f84 GraphicsServices GSEventRunModal + 100框架#24:0x000000018d54367c UIKit`UIApplicationMain + 236
    • 帧#25:0x0000000101063348 OOL <代码>主要位于AppDelegate.swift:22帧#26:0x00000001839e056c libdyld.dylib 开始+ 4
  • thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BREAKPOINT (code=1, subcode=0x1030fcb94) frame #0: 0x00000001030fcb94 libswiftFoundation.dylibfunction signature specialization <Arg[0] = Owned To Guaranteed, Arg[1] = Dead> of static Foundation.URL._unconditionallyBridgeFromObjectiveC(Swift.Optional<__ObjC.NSURL>) -> Foundation.URL + 288 frame #1: 0x0000000103045f24 libswiftFoundation.dylibstatic Foundation.URL._unconditionallyBridgeFromObjectiveC(Swift.Optional<__ObjC.NSURL>) -> Foundation.URL + 20 frame #2: 0x0000000101199c68 OOL@objc PostTableViewCell.textView(_:shouldInteractWith:in:) at PostTableViewCell.swift:0 frame #3: 0x000000018e1e397c UIKit-[_UITextViewInteractableLink allowInteraction:] + 360 frame #4: 0x000000018e1e2698 UIKit-[_UITextViewInteractableItem handleTap] + 40 frame #5: 0x000000018db64548 UIKit-[UITextGestureClusterLinkInteract smallDelayRecognizer:] + 296 frame #6: 0x000000018db7ccd0 UIKit-[UIGestureRecognizerTarget _sendActionWithGestureRecognizer:] + 64 frame #7: 0x000000018db812c4 UIKit_UIGestureRecognizerSendTargetActions + 124 frame #8: 0x000000018d659aa8 UIKit_UIGestureRecognizerSendActions + 320 frame #9: 0x000000018d510c38 UIKit-[UIGestureRecognizer _updateGestureWithEvent:buttonEvent:] + 732 frame #10: 0x000000018db6ab34 UIKit_UIGestureEnvironmentUpdate + 1084 frame #11: 0x000000018db6a6a4 UIKit-[UIGestureEnvironment _deliverEvent:toGestureRecognizers:usingBlock:] + 404 frame #12: 0x000000018db69800 UIKit-[UIGestureEnvironment _updateGesturesForEvent:window:] + 276 frame #13: 0x000000018d50ef44 UIKit-[UIWindow sendEvent:] + 3180 frame #14: 0x000000018d4dff64 UIKit-[UIApplication sendEvent:] + 340 frame #15: 0x000000018de3531c UIKit__dispatchPreprocessedEventFromEventQueue + 2364 frame #16: 0x000000018de378a8 UIKit__handleEventQueueInternal + 4760 frame #17: 0x000000018de307c0 UIKit__handleHIDEventFetcherDrain + 152 frame #18: 0x0000000183fa697c CoreFoundation__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 24 frame #19: 0x0000000183fa68fc CoreFoundation__CFRunLoopDoSource0 + 88 frame #20: 0x0000000183fa6184 CoreFoundation__CFRunLoopDoSources0 + 204 frame #21: 0x0000000183fa3d5c CoreFoundation__CFRunLoopRun + 1048 frame #22: 0x0000000183ec3e58 CoreFoundationCFRunLoopRunSpecific + 436 frame #23: 0x0000000185d70f84 GraphicsServicesGSEventRunModal + 100 frame #24: 0x000000018d54367c UIKit`UIApplicationMain + 236
    • frame #25: 0x0000000101063348 OOLmain at AppDelegate.swift:22 frame #26: 0x00000001839e056c libdyld.dylibstart + 4

推荐答案

我想可能是问题所在(在标签或哈希上)...

What I guess could be the issue (either on tag or hash)...

您这样做:

attrString.addAttribute(NSAttributedStringKey.link, value: "hash://\(stringifiedWord)", range: matchRange)

但是如果您要使用 URL 对象( let url = URL.init(string:" hash://\(stringifiedWord)"))如果字符串网址无效,并且阿拉伯字符似乎无效,您会发现它可能为 nil .

But if you'd use a URL object (let url = URL.init(string:"hash://\(stringifiedWord)")) you'll see it may be nil in case of invalid string url and in your case arabic characters seem to be invalid.

委托方法 func textView(_ textView:UITextView,shouldInteractWith URL:URL,in characterRange:NSRange)->Bool 在参数中提供了一个 URL 对象,由于没有有效的url时不会调用您的方法,因此我猜苹果代码的内线假定它是有效的url,不对其进行检查并崩溃.那可以解释为什么您的方法没有被调用并在进入您的方法之前崩溃了.

The delegate method func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange) -> Bool is giving a URL object in parameters, and because your method is not called when you don't have a valid url, I guess that inner line in Apple's code assume it's a valid url, doesn't check it and crashes. That would explain why your method isn't called and crash before entering yours.

解决方案:使用百分比转义字符.代替放置 value:"hash://\(stringifiedWord)" ,而要做 value:"hash://\((stringifiedWord.addingPercentEncoding(withAllowedCharacters:.urlHostAllowed))''); 或其他字符集.

Solution: Use percent escaped characters. Instead of putting value: "hash://\(stringifiedWord)", do value: "hash://\(stringifiedWord.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed))" or other character set allowed.

在委托方法中,您已经删除了转义百分比: let hash = path.removingPercentEncoding?.components(separatedBy:://").last ,所以您没有在此处添加任何内容.

In the delegate method you are already removing the percent escape: let hash = path.removingPercentEncoding?.components(separatedBy: "://").last so you don't have to add anything there.

附加说明:您正在做 if word.hasPrefix(#")和`if word.hasPrefix("@")几乎相同的事情(只是方案更改),您可以简化/分解,示例代码未经测试:

Additional note: You are doing if word.hasPrefix("#") and `if word.hasPrefix("@") almost the same thing (just the scheme change), you could simplify/factorize that, sample code not tested:

let dict = ["#":"mention://", "@": "hash://"]
for (key, value) in dict
{
   if word.hasPrefix(key)
   {
       let matchRange:NSRange = nsText.range(of: word as String)
       var stringifiedWord:String = word as String
       stringifiedWord = String(stringifiedWord.dropFirst(key.count))
       let espcapedWord  = stringifiedWord.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed
       let stringURL = "\(value)\(escapedWord)"
       if let url = URL.init(string:stringURL) //That should you avoid any crash just in case
       {
           attrString.addAttribute(.link, value: stringURL, range: matchRange)
       }
       else
       {
            print("Oooops with \(stringifiedWord) invalid URL: \(stringURL)")
       }
   }
}

视iOS版本(在Simulator上测试)而定,它可能会崩溃,或者由于URL无效而根本不调用委托方法.

Depending on the iOS version (tested on Simulator), it could make it crash, or simply not call the delegate method because of the invalid URL.

这篇关于阿拉伯语的主题标签使应用程序崩溃的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆