到目前为止,我发现的所有资源都提供了此代码的变体,用于从required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
var view = (Bundle.main.loadNibNamed("MyCustomView", owner: self, options: nil)![0])
self.addSubview(view as! UIView)
}
文件加载视图,但始终实现相同的逻辑:
xib
这对我来说不合适,因为此函数属于UIView的子类,并将预期的设计(self
的设计)添加为子视图。在这种情况下,如果我们向xib
添加了不同的UI元素,它将属于与---self (UIView)
---Other UI elements added by code in `self`
---xib (UIView)
---UI elements in xib file
文件中的UI元素不同的父元素。
所以层次结构看起来像这样:
xib
这不是不必要的包装吗?如果是这样,有没有办法直接将self
文件中的所有视图添加到xib
?或者是否有一种不同的更优雅的方式从// Add a fee of 10.00 when Paypal is chosen
add_action( 'woocommerce_cart_calculate_fees', 'custom_paypal_additional_fee', 20, 1 );
function custom_paypal_additional_fee( $cart ) {
if ( is_admin() && ! defined( 'DOING_AJAX' ) )
return;
if( WC()->session->get( 'chosen_payment_method' ) == 'paypal' )
$cart->add_fee( __( 'Paypal fee', 'woocommerce' ), 10.00 );
}
// Add the information on checkout paypal text gateways section
add_filter('woocommerce_gateway_icon', 'custom_paypal_gateway_text', 20, 2 );
function custom_paypal_gateway_text( $html, $gateway_id ) {
if( $gateway_id == 'paypal' )
$html .= ' <small class="paypal-fee">(+ '.wc_price(10.00).')</small>';
return $html;
}
// Enable ajax update checkout event when choosing a gateway to refresh the fee
add_action('wp_footer', 'payment_gateways_update_checkout_event' );
function payment_gateways_update_checkout_event() {
?>
<script type="text/javascript">
(function($){
$('form.checkout').on( 'change', 'input[name^="payment_method"]', function() {
var t = { updateTimer: !1, dirtyInput: !1,
reset_update_checkout_timer: function() {
clearTimeout(t.updateTimer)
}, trigger_update_checkout: function() {
t.reset_update_checkout_timer(), t.dirtyInput = !1,
$(document.body).trigger("update_checkout")
}
};
$(document.body).trigger('update_checkout')
});
})(jQuery);
</script>
<?php
}
文件加载设计?
答案 0 :(得分:1)
重用一组复杂子视图的一种方法是定义嵌入式视图控制器。首先定义顶级视图控制器。在其中,您定义一个插座并将其连接到子控制器的实例(也在nib中定义)。您还可以将子控制器的view
连接到顶级nib视图层次结构中的占位符UIView
。
class ViewController: UIViewController {
@IBOutlet var childController: ReusableViewController?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
}
在子控制器中发生轻微的手。加载超级控制器时会调用其awakeFromNib
函数。然后,子控制器使用它所连接的“占位符”UIView
将其视图层次结构插入到顶级视图中。
class ReusableViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func awakeFromNib() {
super.awakeFromNib()
// This controller manages a reusable view defined by a seperate nib.
// When defined in the parent nib, its view is connected to a placeholder view object.
// When the nib is loaded, the secondary nib is loaded and replaces the placeholder.
let placeholder = self.view!
Bundle.main.loadNibNamed("ReusableViewController", owner: self, options: nil)
// (the nib connects the view property to the actual view, replacing the placeholder)
placeholder.superview?.insertSubview(self.view, aboveSubview: placeholder)
// (do something about constraints here?)
placeholder.removeFromSuperview()
}
}
这种安排的优点是子控制器可以具有所需的任何绑定,出口,操作,连接,属性和业务逻辑,整齐地封装和可重用。
这有点像黑客攻击,因为它会使子控制器的视图加载生命周期短路(因为控制器永远不会加载自己的视图)。要解决这个问题,您可以定义另一个属性,该子属性将子控制器指向占位符视图或应插入其自身的容器视图。然后用Bundle.main.loadNibName(blah, blah, blah)
替换let replacement = self.view
内容,让视图控制器完成所有加载。
这是一个完成的解决方案,使用原始海报提供的故事板,让它开始工作
在故事板中使用可重复使用的视图
将Container View
(不要与View
混淆)添加到ViewController
(故事板上的主视图),并将其场景(控制器)类设置为我们刚刚定义的控制器({{1 }})。
而已。这样,您可以向视图添加任意数量的子视图,而无需在故事板和代码中包装子视图
ReusableViewController
的预期用途实际上是为了这个目的而被记录here
答案 1 :(得分:0)
通常,当您为视图实现xib时,它始终包含所有必需的元素。但如果你有,你可以尝试添加像这样的元素
var view = (Bundle.main.loadNibNamed("MyCustomView", owner: self, options: nil)![0]) as! UIView
var lbl = UILabel()
lbl.frame = //.....
view.addSubview(lbl)
self.addSubview(view)
答案 2 :(得分:0)
You can load the xib of a view during init:
init() {
super.init(nibName: "ViewController", bundle: Bundle(identifier: "domain.AppName")!)
self.loadView()
}
Is that what your are looking for?
答案 3 :(得分:0)
这是您一直想要的答案。您可以只创建CustomView
类,并将其主实例包含在带有所有子视图和出口的xib中。然后,您可以将该类应用于情节提要或其他xib中的任何实例。
无需摆弄File的所有者,或将插座连接到代理,也无需以特殊方式修改xib,或将自定义视图的实例添加为其自身的子视图。
只需执行以下操作:
UIView
更改为NibView
(或从UITableViewCell
更改为NibTableViewCell
)就是这样!
它甚至可以与IBDesignable一起使用,以在设计时在情节提要中引用您的自定义视图(包括来自xib的子视图)。
您可以在此处了解更多信息: https://medium.com/build-an-app-like-lego/embed-a-xib-in-a-storyboard-953edf274155
您可以在此处获得开源的BFWControls框架: https://github.com/BareFeetWare/BFWControls
以下是驱动它的NibReplaceable
代码的简单摘录,以防您好奇:https://gist.github.com/barefeettom/f48f6569100415e0ef1fd530ca39f5b4
汤姆