Swift 4 @IBAction UIButton操作未正确调用

时间:2019-03-02 20:29:40

标签: ios swift uibutton ibaction

我知道这个问题在这个网站上经常被问到,但是我看过的每个问题都有不同的答案,并且我已经尝试了每个问题。

我有一个放置在情节提要中的UIButton,并将其连接到视图控制器中的@IBAction。每次单击按钮时,都会显示错误-[UIViewController openAlert]: unrecognized selector sent to instance

该函数没有参数(我尝试过使用sender参数,它调用openAlertWithSender而不是openAlert(sender:)),我发现将按钮连接到类顶部的变量将可以工作,但这给了我一个新错误:This class is not key value coding-compliant

我确保按钮已正确连接到情节提要中的功能,并且确保在视图中启用了用户交互。

我尝试以编程方式构建按钮,但它根本不会出现在屏幕上。

无论我做什么,我似乎都无法使此按钮正常工作。

我的代码:

class OfflineViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)

    // Hide the navigation bar
        navigationController?.setNavigationBarHidden(true, animated: animated)

        NetworkHandler.shared.addListener(listener: self)
    }

    override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)

        // Show the navigation bar
        navigationController?.setNavigationBarHidden(false, animated: animated)
    }

    override func viewDidDisappear(_ animated: Bool) {
        super.viewDidDisappear(animated)

        NetworkHandler.shared.removeListener(listener: self)

    }

    private func showMainController() -> Void {
        DispatchQueue.main.async {
            self.performSegue(withIdentifier: "NetworkAvailable", sender: self)
        }
    }

    @IBAction func openAlert() {
        let alert = UIAlertController(title: "Clicked", message: "You have clicked on the button", preferredStyle: .alert)

        self.present(alert, animated: true, completion: nil)
    }


}

感谢您的帮助。

1 个答案:

答案 0 :(得分:0)

首先请确保您已将IB中的类名称分配给vc public class DevicesListFragment extends Fragment implements RecyclerItemTouchHelper.RecyclerItemTouchHelperListener { private List<Device> deviceList = new ArrayList<>(); private RecyclerView recyclerView; private DevicesAdapter mAdapter; private RelativeLayout relativeLayout; private int buttonR_ID; private SwipeRefreshLayout swipe; EditText SETnameDevice, SETnameDivision; FloatingActionButton addDevice; EditText nameDevice; EditText nameDivision; Switch switchOnOffDevice; Spinner spTipoDevice; Spinner spTipoDivision; Device device; static ArrayList<Device> devices = new ArrayList<>(); DataCommunicationHome mCallback; public DevicesListFragment() { this.buttonR_ID = buttonR_ID; // Required empty public constructor } public void setID(int buttonR_ID) { this.buttonR_ID = buttonR_ID; } @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { // Inflate the layout for this fragment View view = inflater.inflate(R.layout.fragment_devices_list, container, false); setHasOptionsMenu(true);//Make sure you have this line of code. recyclerView = (RecyclerView) view.findViewById(R.id.recycler_view); relativeLayout = (RelativeLayout) view.findViewById(R.id.relative_layout); deviceList = new ArrayList<>(); mAdapter = new DevicesAdapter(getContext(), deviceList); RecyclerView.LayoutManager mLayoutManager = new LinearLayoutManager(getContext()); recyclerView.setLayoutManager(mLayoutManager); recyclerView.setItemAnimator(new DefaultItemAnimator()); recyclerView.setAdapter(mAdapter); swipe = view.findViewById(R.id.swiperefresh); swipe.setColorSchemeResources(R.color.colorAccent, R.color.darkGrey); swipe.setOnRefreshListener(new SwipeRefreshLayout.OnRefreshListener() { @Override public void onRefresh() { refresh(); } }); // adding item touch helper // only ItemTouchHelper.LEFT added to detect Right to Left swipe // if you want both Right -> Left and Left -> Right // add pass ItemTouchHelper.LEFT | ItemTouchHelper.RIGHT as param ItemTouchHelper.SimpleCallback itemTouchHelperCallback = new RecyclerItemTouchHelper(0, ItemTouchHelper.LEFT,this ); new ItemTouchHelper(itemTouchHelperCallback).attachToRecyclerView(recyclerView); prepareDeviceData(); /************************** FLOATING BUTTON **************************************************/ addDevice = view.findViewById(R.id.add_device_buttom); addDevice.setOnClickListener( new Button.OnClickListener() { @Override public void onClick(View view) { AlertDialog.Builder mBuilder = new AlertDialog.Builder(getContext()); final View viewDialog = getLayoutInflater().inflate(R.layout.dialog_add_device, null); nameDevice = (EditText) viewDialog.findViewById(R.id.name_device); switchOnOffDevice = (Switch) viewDialog.findViewById(R.id.switch_dialog); nameDivision = (EditText) viewDialog.findViewById(R.id.name_division); //########################### Spinner categorias devices ####################################### spTipoDevice = (Spinner) viewDialog.findViewById(R.id.spinnerTipoDevice); ArrayAdapter<String> adapter = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item, getResources().getStringArray(R.array.device_cat_items)); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spTipoDevice.setAdapter(adapter); //########################### Spinner categorias Divisions ####################################### spTipoDivision = (Spinner) viewDialog.findViewById(R.id.spinnerDivisao); ArrayAdapter<String> adapter2 = new ArrayAdapter<String>(getContext(), android.R.layout.simple_spinner_item, getResources().getStringArray(R.array.divisions_cat_items)); adapter2.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spTipoDivision.setAdapter(adapter2); // ################################## BUTTONS ######################################################## mBuilder.setPositiveButton("CREATE", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int which) { String deviceSTR = nameDevice.getText().toString(); String divisionSTR = nameDivision.getText().toString(); String deviceCat = spTipoDevice.getSelectedItem().toString(); String divisionCat = spTipoDivision.getSelectedItem().toString(); int onoff; if (switchOnOffDevice.isChecked()) onoff = 1; else onoff = 0; if (!deviceSTR.isEmpty() && !divisionSTR.isEmpty() && !deviceCat.equalsIgnoreCase("Choose a device type...") && !divisionCat.equalsIgnoreCase("Choose a division type...")) { Toast.makeText(getContext(), "Device created", Toast.LENGTH_SHORT).show(); device = new Device(deviceSTR, onoff, deviceCat, divisionSTR, divisionCat); devices.add(device); mCallback.setArrayListDevices(devices); dialogInterface.dismiss(); } else { Toast.makeText(getContext(), "Device not created", Toast.LENGTH_SHORT).show(); dialogInterface.dismiss(); } } }); mBuilder.setNegativeButton("EXIT", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int which) { dialogInterface.dismiss(); } }); mBuilder.setView(viewDialog); AlertDialog dialog = mBuilder.create(); dialog.show(); dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setTextColor(Color.RED); } }); /************************** END Floating Button **************************************************/ recyclerView.addOnItemTouchListener(new RecyclerTouchListener(getContext(), recyclerView, new RecyclerTouchListener.ClickListener() { @Override public void onClick(View view, int position) { Device device = deviceList.get(position); if(device.getOnOff() == 1) { device.setOnOff(0); mAdapter.notifyDataSetChanged(); } else if(device.getOnOff() == 0) { device.setOnOff(1); mAdapter.notifyDataSetChanged(); } } @Override public void onLongClick(View view, final int position) { AlertDialog.Builder mBuilder = new AlertDialog.Builder(getContext()); final View viewDialog = getLayoutInflater().inflate(R.layout.dialog_change_device_info, null); SETnameDevice = (EditText) viewDialog.findViewById(R.id.name_device_change); SETnameDivision = (EditText) viewDialog.findViewById(R.id.name_division_change); mBuilder.setPositiveButton("CHANGE", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int which) { String deviceSTR = SETnameDevice.getText().toString(); String divisionSTR = SETnameDivision.getText().toString(); if (!deviceSTR.isEmpty()) { deviceList.get(position).setNameDevice(deviceSTR); mCallback.setArrayListDevices(devices); mAdapter.notifyDataSetChanged(); Toast.makeText(getContext(), "Device changed", Toast.LENGTH_SHORT).show(); dialogInterface.dismiss(); } if(!divisionSTR.isEmpty()) { deviceList.get(position).setNameDivision(divisionSTR); mCallback.setArrayListDevices(devices); mAdapter.notifyDataSetChanged(); Toast.makeText(getContext(), "Device changed", Toast.LENGTH_SHORT).show(); dialogInterface.dismiss(); } } }); mBuilder.setNegativeButton("EXIT", new DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialogInterface, int which) { dialogInterface.dismiss(); } }); mBuilder.setView(viewDialog); AlertDialog dialog = mBuilder.create(); dialog.show(); dialog.getButton(DialogInterface.BUTTON_NEGATIVE).setTextColor(Color.RED); } })); return view; } private void prepareDeviceData() { if (deviceList.size() > 0) { for (int i = 0; i < deviceList.size(); i++) { deviceList.remove(i); mAdapter.notifyItemRemoved(i); } } ArrayList<Device> devicesAuxiliar = new ArrayList<Device>(); Device d1 = new Device("Radiator", 0, getString(R.string.thermostats_str), "Bucatarie 1", "Bucatarie"); devicesAuxiliar.add(d1); Device d2 = new Device("Bec", 0, getString(R.string.lights_str), "Gradina", "Gradina"); devicesAuxiliar.add(d2); Device d3 = new Device("Bec", 0, getString(R.string.lights_str), "Bucatarie 1", "Bucatarie"); devicesAuxiliar.add(d3); Device d4 = new Device("Bec", 0, getString(R.string.lights_str), "Sufragerie", "Sufragerie"); devicesAuxiliar.add(d4); Device d5 = new Device("Bec", 0, getString(R.string.lights_str), "Hol", "Hol"); devicesAuxiliar.add(d5); Device d6 = new Device("Bec", 0, getString(R.string.lights_str), "Garaj", "Garaj"); devicesAuxiliar.add(d6); Device d7 = new Device("Usa", 0, getString(R.string.doors_st_r), "Gradina", "Gradina"); devicesAuxiliar.add(d7); Device d8 = new Device("Poarta Masina", 0, getString(R.string.doors_st_r), "Curte", "Curte"); devicesAuxiliar.add(d8); Device d9 = new Device("Usa", 0, getString(R.string.doors_st_r), "Casa", "Casa"); devicesAuxiliar.add(d9); if(!mCallback.getArrayListDevices().isEmpty()); devicesAuxiliar.addAll(mCallback.getArrayListDevices()); int BotaoID = mCallback.getIDButtonDevices(); for(Device device : devicesAuxiliar) { if (BotaoID == R.id.card_smart_lights) if (device.getDeviceType().equals(getString(R.string.lights_str))) deviceList.add(device); if (BotaoID == R.id.card_smart_plugins) if (device.getDeviceType().equals(getString(R.string.smart_plugin_str))) deviceList.add(device); if (BotaoID == R.id.card_thermostats) if (device.getDeviceType().equals(getString(R.string.thermostats_str))) deviceList.add(device); if(BotaoID == R.id.card_Doors) if(device.getDeviceType().equals(getString(R.string.doors_st_r))) deviceList.add(device); if(BotaoID == 0) if(device.getNameDivision().equalsIgnoreCase(mCallback.getArrayListDevices().get(0).getNameDivision())) deviceList.add(device); } mAdapter.notifyDataSetChanged(); } public void refresh() { new Handler().postDelayed(new Runnable() { @Override public void run() { if (deviceList.size() > 0) { for (int i = 0; i < deviceList.size(); i++) { deviceList.remove(i); mAdapter.notifyItemRemoved(i); } } prepareDeviceData(); swipe.setRefreshing(false); //ola. // ola2 // ola 3 // ola 4. } }, 1000); } /** * callback when recycler view is swiped * item will be removed on swiped * undo option will be provided in snackbar to restore the item */ @Override public void onSwiped(RecyclerView.ViewHolder viewHolder, int direction, int position) { if (viewHolder instanceof DevicesAdapter.MyViewHolder) { // get the removed item name to display it in snack bar String name = deviceList.get(viewHolder.getAdapterPosition()).getNameDevice(); // backup of removed item for undo purpose final Device deletedItem = deviceList.get(viewHolder.getAdapterPosition()); final int deletedIndex = viewHolder.getAdapterPosition(); // remove the item from recycler view mAdapter.removeItem(viewHolder.getAdapterPosition()); // showing snack bar with Undo option Snackbar snackbar = Snackbar .make(relativeLayout, name + " removed from cart!", Snackbar.LENGTH_LONG); snackbar.setAction("UNDO", new View.OnClickListener() { @Override public void onClick(View view) { // undo is selected, restore the deleted item mAdapter.restoreItem(deletedItem, deletedIndex); } }); View view = snackbar.getView(); CoordinatorLayout.LayoutParams params =(CoordinatorLayout.LayoutParams)view.getLayoutParams(); params.gravity = Gravity.TOP; view.setLayoutParams(params); snackbar.setActionTextColor(Color.YELLOW); snackbar.show(); } } @Override public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) { devicesAuxiliar.add super.onCreateOptionsMenu(menu, inflater); } @Override public void onAttach(Context context) { super.onAttach(context); // This makes sure that the container activity has implemented // the callback interface. If not, it throws an exception try { mCallback = (DataCommunicationHome) context; } catch (ClassCastException e) { throw new ClassCastException(context.toString() + " must implement DataCommunication"); } } public void showDevicesListFragment(int rID) { mCallback.setIDButtonDevices(rID); Fragment fr = new DevicesListFragment(); FragmentChangeListener fc=(FragmentChangeListener)getActivity(); fc.replaceFragment(fr); }

第二个添加此方法

OfflineViewController

似乎您在将其命名为@IBAction func printMessage(_ sender:UIButton) { } 之后更改了它的名称,而不是openAlert,并且IB封装了不再存在的旧名称,因此崩溃了

  

注意:情节提要是幕后的xml文件,因此每个插口名称/动作名称都会保留,直到您对其进行更改为止,并​​且没有错误机制可以告诉您何时编译