我的@IBAction func searchcode(sender: UIButton) {
//searchcodebtn.addTarget(self, action: "buttonPressed:", forControlEvents: .TouchUpInside)
searchCode()
}
func searchCode(){
let keyword = self.searchcodetxt.text
let lowercasekeyword = keyword!.lowercaseString
let baseString = webcode.text
let baselowercase = baseString!.lowercaseString
let attributed = NSMutableAttributedString(string: baseString)
var error: NSError?
do {
let regex = try NSRegularExpression(pattern: lowercasekeyword, options: NSRegularExpressionOptions.CaseInsensitive)
let matches = regex.matchesInString(baselowercase, options: [], range: NSMakeRange(0, baselowercase.characters.count))
if let match = matches.first {
let range = match.rangeAtIndex(1)
if let swiftRange = rangeFromNSRange(range, forString: baselowercase) {
attributed.addAttribute(NSBackgroundColorAttributeName, value: UIColor.yellowColor(), range: match.range)
}
}
webcode.attributedText = attributed
} catch {
// regex was bad!
let alertView:UIAlertView = UIAlertView()
alertView.title = "Keywords error!"
alertView.message = "Please use another keywords"
alertView.delegate = self
alertView.addButtonWithTitle("OK")
alertView.show()
// Delay the dismissal by 5 seconds
let delay = 5.0 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue(), {
alertView.dismissWithClickedButtonIndex(-1, animated: true)
})
}
}
func rangeFromNSRange(nsRange: NSRange, forString str: String) -> Range<String.Index>? {
let fromUTF16 = str.utf16.startIndex.advancedBy(nsRange.location, limit: str.utf16.endIndex)
let toUTF16 = fromUTF16.advancedBy(nsRange.length, limit: str.utf16.endIndex)
if let from = String.Index(fromUTF16, within: str),
let to = String.Index(toUTF16, within: str) {
return from ..< to
}
return nil
}
,<main>
和<div>
之间存在父子控制器关系:
<my-directive>
在MainController中,我使用:
执行$ broadcast<main ng-controller="MainController">
<nav>
<ul>
<li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
</ul>
</nav>
<div ng-controller="AboutController">
</div>
<my-directive></my-directive>
</main>
在AboutController中,我可以通过以下方式成功接收这个$ broadcast:
$scope.$broadcast('shoppingCartReady', msg);
但是,当试图在angular.module('aboutModule', [])
.controller('AboutController', require('./about/aboutController'));
var AboutController = function ($scope, $rootScope) {
$scope.$on('shoppingCartReady', function(event, msg){
console.log(msg);
});
};
module.exports = [ '$scope', '$rootScope', AboutController];
链接功能中接收$ broadcast时,似乎永远不会收到:
<my-directive>
更新
我甚至在我的指令中创建了一个控制器:
angular.module('shopModule', [])
.directive('shopModuleDirective', require('./shopModuleDirective'))
.directive('myDirective', require('./myDirective'));
var myDirective = function ($rootScope) {
function link($scope, element, attrs, baseCtrl) {
$scope.$on('shoppingCartReady', function (event, msg) {
console.log(msg);
});
}
return {
restrict: 'E',
require: '^shopModuleDirective',
link: link
};
};
return ['$rootScope', myDirective];
我可以看到
的日志angular.module('shopModule', [])
.directive('shopModuleDirective', require('./shopModuleDirective'))
.directive('myDirective', require('./myDirective'));
var myDirective = function ($rootScope) {
var controller = ["$scope", "$element", function ($scope, element) {
console.log('waiting for .on....');
$scope.$on('shoppingCartReady', function (event, cache) {
console.log('shoppingCartReady .on rcvd!');
});
}]
function link($scope, element, attrs, baseCtrl) {
$scope.$on('shoppingCartReady', function (event, msg) {
console.log(msg);
});
}
return {
restrict: 'E',
require: '^shopModuleDirective',
link: link
};
};
return ['$rootScope', myDirective];
但.on从未收到。
更新:
我认为可能的原因是由于范围没有“准备好”。
在MainController的原始console.log('waiting for .on....');
内,如果我在broadcast
之后执行另一个,则会收到所有setTime
:
MainController:
.on
答案 0 :(得分:4)
$ broadcast(name,args);
将事件名称向下调度到所有子范围(以及他们的 孩子们)通知已注册的$ rootScope.Scope听众。
在你的指令中,你没有创建一个新的范围,我猜你和MainController
只是在同一范围内。在这种情况下,您不在MainController
的childScope中,因此无法在那里触发事件。我会尝试下列之一:
始终通过$rootScope.$broadcast
广播您的活动。所有其他范围都是$rootScope
的孩子,所以只要您注册$scope.$on
的活动,您就会收到它。您可能还对Why do we use $rootScope.$broadcast in AngularJS?
将您的指令设为隔离的$scope
。这将作为MainController
的childScope,并且应该也可以。 Isolationg the $scope of a directive
除了选项1.
,您还可以将$rootScope.$emit
与$rootScope.$on
一起使用。有关详细信息,请阅读$rootScope.$broadcast vs. $scope.$emit
我总是选择选项1.
,因为有时你不希望你的指令有一个孤立的范围。
答案 1 :(得分:3)
有竞争条件。
在myDirective
之后执行 MainController
控制器和后链接功能,并在触发shoppingCartReady
事件后设置侦听器。
良好的,可测试的指令设计的经验法则是将所有与范围相关的逻辑保留在控制器中,链接函数和$onInit
挂钩完全用于那里应该发生的事情而不是其他任何地方,比如操作关于编译的DOM内容。
link
不太明显但独特的用例是理想的执行顺序(后连接函数以相反的顺序执行,从子项到父项)。如果MainController
成为指令,并且scope.$broadcast('shoppingCartReady', msg)
在link
函数而不是控制器中执行,则可以保证正确的执行顺序。
将控制器代码包装为零$timeout
也会推迟代码
$timeout(function(){
$scope.$broadcast('shoppingCartReady', msg);
});
在子指令中链接函数后执行,但也会指定一些代码味道。这是范围事件不太可取的指令通信方式并且容易出现反模式的原因之一。
处理这种情况的另一种方法取决于shoppingCartReady
事件的内容,但在目前的情况下它是多余的:它已经发生在执行子控制器时,它们可以安全地假设'购物车准备好了。
有关此主题的建议阅读材料:Directive Controller And Link Timing In AngularJS。