为什么instantiateViewControllerWithIdentifier需要使用" as!"

时间:2016-05-14 03:45:34

标签: ios swift

@Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_search);
        Toolbar toolbar = (Toolbar) findViewById(R.id.toolbar);
        setSupportActionBar(toolbar);

        actionBar = getSupportActionBar();

        if (actionBar != null)
            initializeActionBar();

        if (getSupportActionBar() != null)
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);

        Log.d(TAG, "on create");

        if (savedInstanceState != null) {
            Log.d(TAG, "saved instance state not null");
            if (savedInstanceState.getString("search_text") != null)
                etSearch.setText(savedInstanceState.getString("search_text"));
        }
    }

    @Override
    public void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putString("search_text", etSearch.getText().toString());
        Log.d(TAG, "on Save instance state");
    }

    @Override
    protected void onRestoreInstanceState(Bundle savedInstanceState) {
        super.onRestoreInstanceState(savedInstanceState);

        Log.d(TAG, "on restore instance state");

        if (savedInstanceState != null) {
            if (savedInstanceState.getString("search_text") != null)
              etSearch.setText(savedInstanceState.getString("search_text"));
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        Log.d(TAG, "on resume");
    }

    @Override
    protected void onStop() {
        super.onStop();
        Log.d(TAG, "on stop");
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.d(TAG, "on destroy");
    }

private void initializeActionBar() {

    actionBar.setCustomView(R.layout.actionbar_with_edittext);

    etSearch = (EditText) actionBar.getCustomView().findViewById(R.id.actionbar_searchfield);
    etSearch.setOnEditorActionListener(new TextView.OnEditorActionListener() {

        @Override
        public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {

            if(event != null && event.getKeyCode() == KeyEvent.KEYCODE_ENTER && event.getAction() == KeyEvent.ACTION_DOWN) {
                initiateNewSearch();
                etSearch.clearFocus();

            }

            return false;
        }
    });

    InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
    imm.showSoftInput(etSearch, InputMethodManager.SHOW_IMPLICIT);
    etSearch.requestFocus();
}

为什么我们需要使用" as! DataEntryViewController"

当我使用xcode 7.3.1

取出它时,它会起作用

1 个答案:

答案 0 :(得分:1)

定义“工作”。

是的,您可以实例化视图控制器,而无需关心它是UIViewController的哪个子类。并且从该方法返回的对象将是一个视图控制器,因此可以对所有视图控制器执行操作是安全的:以模态方式呈现它,将其推送到导航控制器,将其添加到选项卡控制器,等。

但是,如果您打算使用特定于视图控制器类的内容 - 例如SomethingViewController定义了一个属性,可以让您选择显示的Something,并且您想要要分配给该属性 - 您需要做两件事:

  1. 在运行时测试从instantiateViewControllerWithIdentifier返回的对象是您期望的对象。 (因为根据您传递的标识符,它可能是其他类,如果该标识符不在故事板中,则根本没有任何内容。)
  2. 让编译器知道为该类键入了您为该对象分配的变量,以便编译器允许您访问属性并调用该类的方法。
  3. 使用as?as!广告投放分配可以一步完成这两项任务。 (是否使用as?as!只取决于您对自己的信任程度,以确保您的故事板标识符是他们声称的,以及您希望如何处理此类假设的失败。)

    实际上,即使您没有使用特定于该视图控制器类的属性或方法,as!强制转换也会添加运行时检查,以确保您的视图控制器类符合您的预期。因此,当你进行投射时没有任何破坏这一事实并不表明施法是多余的 - 这表明施法者正在检查的任何破损目前都没有发生。

    也就是说,如果有人更改了您的故事板,那么您引用的行会导致崩溃,因此标识符“某事”位于SomethingElseViewController上。如果你把那个甩掉了,你就不会在那里崩溃。 (你以后可能会遇到麻烦。)

    但是,如果你真正想做的是断言你的故事板和程序的有效性,那么最好明白这一点:

    let someVC  = self.storyboard!.instantiateViewControllerWithIdentifier("something")
    assert(someVC is SomethingViewController)
    // then do something non-SomethingViewController-specific with it