實現輸入@彈出列表選擇,顯示@xxx,退格@xxx直接刪除效果

weixin_34365417發表於2016-05-09

好久沒寫文章了,荒廢了一段時間,今天來寫一個退格刪除@xxx的小文章!
想必大家都用過,就是在使用微信或者QQ群聊的時候,你@xxx的時候,退格了,@xxx直接消失了,大概就是這麼一個效果。

注:

最近在自學swift,所以這次的程式碼是用swift寫的,因為剛上手一個周的swift,如果程式碼寫得很難看請見諒!
其實寫法還是跟Objective-C差不多,看大概也能看得懂!

實現這個效果最主要的就是用到這個UITextFieldDelegate中的一個方法:

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, 
replacementString string: String) -> Bool

1.先判斷在輸入框輸入@彈出聯絡人列表的情況

這裡如果使用者輸入@,這裡彈出聯絡人列表選擇

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        if string == "@" {
            self.location = range.location;
            self.remarkText = textField.text!;
            // Present MemberViewController
            let memberVC: MemberViewController = MemberViewController();
            memberVC.delegate = self;
            memberVC.presentedMemberList = true;
            let naviMemberVC: UINavigationController = UINavigationController.init(rootViewController: memberVC);
            self.presentViewController(naviMemberVC, animated: true, completion: {
                return true;
            });
        }
        else{
            這裡是輸入或者刪除,下面會介紹
        }

self.location是NSInterger型別,記錄此時輸入游標的位置
self.remarkText是String型別,記錄此時的UITextField的text值

2.接著說明選擇聯絡人之後的返回情況

我這裡返回聯絡人用String表示聯絡人姓名,如果一次選擇了多個使用者我會用 "xxx,yyy,zzz"字串表示。

            // Remark Location
            var startLocation: NSInteger = self.location;
            let nameArray: NSArray = name.componentsSeparatedByString(",") as NSArray;
            for index in 0..<nameArray.count {
                let nameValue: String = "@" + (nameArray.objectAtIndex(index) as! String);
                let rangeDictionary: NSMutableDictionary = NSMutableDictionary.init(objects: [nameValue.characters.count, startLocation, startLocation + nameValue.characters.count, IDArray.objectAtIndex(index)], forKeys: ["length", "startLocation", "endLocation", "ID"]);
                self.rangeArray.addObject(rangeDictionary);
                startLocation += nameValue.characters.count;
                self.remarkText += nameValue;
            }
            // Sort RangeArray By Ascend
            self.rangeArray.sortUsingDescriptors(NSArray.init(array: [NSSortDescriptor.init(key: "startLocation", ascending: true)]) as! [NSSortDescriptor]);
            self.textField.text = self.remarkText;

區域性變數startLocation記錄當前位置
nameArray是聯絡人陣列,因為我用的是String字串,所以這裡分割成陣列,以","分割
然後迴圈nameArray聯絡人陣列,把裡面的名稱xxx -> @xxx
這裡我新建一個可變字典,記錄這個聯絡人的字串 長度,起始位置,終點位置,ID(聯絡人ID,我這邊是用於上傳給伺服器)
最後是這個可變字典以startLocation排序,最小的在最前面,賦值給textField即可。

3.最後是在輸入框輸入或者刪除的情況

這裡有幾種情況,分別是
3.1 在@xxx後面點選退格操作,這個時候需要刪除@xxx字串,並且對後方的@yyy結構裡面的起始位置和終點位置進行前移
3.2 在@xxx中間新增或者退格操作,首先先把這個@xxx的字典刪除,這裡已經破壞了@xxx這個結構,而且@xxx後面的@yyy,@zzz(如果存在的話),需要對所屬字典的起始位置和終點位置進行前進或者退格
3.3 在@xxx結構前面或者後面進行新增操作或者退格操作,這裡跟3.2類似,就是輸入游標後面的@xxx結構裡面的起始位置和終點位置進行前進或者退格操作

注:這裡是接著UITextFieldDelegate那個方法的else

            let currentLocation: NSInteger = range.location;
            for index in 0..<self.rangeArray.count {
                let tempDic: NSMutableDictionary = self.rangeArray.objectAtIndex(index) as! NSMutableDictionary;
                let length: NSInteger = tempDic.objectForKey("length") as! NSInteger;
                let startLocation: NSInteger = tempDic.objectForKey("startLocation") as! NSInteger;
                let endLocation: NSInteger = tempDic.objectForKey("endLocation") as! NSInteger;
                let arrayIndex: NSInteger = tempDic.objectForKey("ID") as! NSInteger;
                
                // Delete
                if currentLocation == endLocation - 1 {
                    var temp: NSString = textField.text! as NSString;
                    temp = temp.stringByReplacingCharactersInRange(NSMakeRange(startLocation, length), withString: "");
                    textField.text = temp as String;
                    // Move Other Location
                    for subIndex in (index+1)..<self.rangeArray.count {
                        let subTempDic: NSMutableDictionary = self.rangeArray.objectAtIndex(subIndex) as! NSMutableDictionary;
                        subTempDic.setObject(subTempDic.objectForKey("startLocation") as! NSInteger - length, forKey: "startLocation");
                        subTempDic.setObject(subTempDic.objectForKey("endLocation") as! NSInteger - length, forKey: "endLocation");
                    }
                    // Delete Data
                    self.rangeArray.removeObjectAtIndex(index);
                    self.userIDArray.removeObject(arrayIndex);
//                    self.userIDArray.removeObjectAtIndex(arrayIndex);
                    return false;
                }
                // Change @xxx Style
                else if currentLocation > startLocation && currentLocation < endLocation {
                    // Delete Content
                    if string.characters.count == 0 {
                        // Move Other Location
                        for subIndex in (index+1)..<self.rangeArray.count {
                            let subTempDic: NSMutableDictionary = self.rangeArray.objectAtIndex(subIndex) as! NSMutableDictionary;
                            subTempDic.setObject(subTempDic.objectForKey("startLocation") as! NSInteger - 1, forKey: "startLocation");
                            subTempDic.setObject(subTempDic.objectForKey("endLocation") as! NSInteger - 1, forKey: "endLocation");
                        }
                        self.rangeArray.removeObjectAtIndex(index);
                        self.userIDArray.removeObject(arrayIndex);
//                        self.userIDArray.removeObjectAtIndex(arrayIndex);
                        return true;
                    }
                    // Add Content
                    else{
                        // Move Other Location
                        for subIndex in (index+1)..<self.rangeArray.count {
                            let subTempDic: NSMutableDictionary = self.rangeArray.objectAtIndex(subIndex) as! NSMutableDictionary;
                            subTempDic.setObject(subTempDic.objectForKey("startLocation") as! NSInteger + string.characters.count, forKey: "startLocation");
                            subTempDic.setObject(subTempDic.objectForKey("endLocation") as! NSInteger + string.characters.count, forKey: "endLocation");
                        }
                        self.rangeArray.removeObjectAtIndex(index);
                        self.userIDArray.removeObject(arrayIndex);
//                        self.userIDArray.removeObjectAtIndex(arrayIndex);
                        return true;
                    }
                }
            }
            // Judge Loop Agagin ?
            for index in 0..<self.rangeArray.count {
                let tempDic: NSMutableDictionary = self.rangeArray.objectAtIndex(index) as! NSMutableDictionary;
                let startLocation: NSInteger = tempDic.objectForKey("startLocation") as! NSInteger;
                if currentLocation < startLocation {
                    // Move Location
                    if string.characters.count == 0 {
                        // Delete Content
                        for subIndex in index..<self.rangeArray.count {
                            let subTempDic: NSMutableDictionary = self.rangeArray.objectAtIndex(subIndex) as! NSMutableDictionary;
                            subTempDic.setObject(subTempDic.objectForKey("startLocation") as! NSInteger - 1, forKey: "startLocation");
                            subTempDic.setObject(subTempDic.objectForKey("endLocation") as! NSInteger - 1, forKey: "endLocation");
                        }
                        return true;
                    }
                    else{
                        // Add Content
                        for subIndex in index..<self.rangeArray.count {
                            let subTempDic: NSMutableDictionary = self.rangeArray.objectAtIndex(subIndex) as! NSMutableDictionary;
                            subTempDic.setObject(subTempDic.objectForKey("startLocation") as! NSInteger + string.characters.count, forKey: "startLocation");
                            subTempDic.setObject(subTempDic.objectForKey("endLocation") as! NSInteger + string.characters.count, forKey: "endLocation");
                        }
                        return true;
                    }
                }
                else{
                    continue;
                }
            }

這裡先定義區域性變數currentLocation記錄當前的游標位置
然後迴圈判斷可變字典陣列(就是擁有多少個@xxx)
第一個if條件是:
在@xxx位置點選退格,就刪除@xxx字串,然後把後面的@yyy結構中起始和終點位置分別前移@xxx字串的長度
第二個if條件是:
在@xxx結構當中新增或者退格操作,導致此結構破壞,然後對後續的@yyy結構進行前進或者後移操作
如果都不存在這個情況,就是在@xxx結構前面或者後面進行新增或者退格操作,這個時候就迴圈一次,找到游標後的第一個@xxx結構,然後進行前移或者後退操作。

注:這裡string.characters.count == 0代表退格操作,在Objective-C那邊就是string.length == 0的意思!還有,這裡沒有全選刪除操作的判斷,如果這裡進行全選刪除的話,記錄的聯絡人ID不會操作!

具體的效果圖就不上了,就寫到這裡了。

相關文章