skip to Main Content

I’m having trouble saving user credentials on ios version of my flutter app.

I have implemented the AutofillGroup and autofillHints also I added the associate domains, here you can see the code and the Xcode setup:

import 'package:easy_localization/easy_localization.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_fimber/flutter_fimber.dart';
import 'package:get_it/get_it.dart';
import 'package:medfyle/bloc/auth/auth_form_cubit.dart';
import 'package:medfyle/presentation/theme/theme.dart';

import '../../../bloc/user/user_bloc.dart';
import '../../../navigator.dart';
import '../../component/mixin/custom_tracker.dart';
import '../../component/mixin/loading.dart';
import '../../component/mixin/manage_error.dart';
import '../../component/widget/appbar/base_app_bar.dart';
import '../../component/widget/custom_button.dart';

class LoginPage extends StatefulWidget {
  static const routeName = '/login_page';

  const LoginPage({Key? key}) : super(key: key);

  @override
  State<LoginPage> createState() => _LoginPageState();
}

class _LoginPageState extends State<LoginPage>
    with Loading, ManageError, CustomTracker {
  @override
  Widget build(BuildContext context) {
    trackScreenWithName(traceName: LoginPage.routeName);
    return BlocProvider<AuthFormBlocCubit>(
      create: (BuildContext context) => GetIt.instance.get<AuthFormBlocCubit>(),
      child: Scaffold(
          appBar: BaseAppBar(label: "auth.login.title".tr()),
          body: SafeArea(
            child: BlocListener<UserBloc, UserState>(
              listener: (context, state) {
                if (state is UserIsLoading) {
                  showLoader(context);
                }
                if (state is UserLoginError) {
                  manageError(context, state.error,
                      showDialog: state.showDialog,
                      showSnack: false,
                      dialogCb: hideLoader(context));
                  hideLoader(context);
                  Fimber.e(state.error.toString());
                }
                if (state is UserIsLogged) {
                  N.goToHome(context);
                }
              },
              child: Padding(
                padding: kDefaultPadding,
                child: BlocBuilder<AuthFormBlocCubit, AuthFormState>(
                    builder: (context, state) {
                  return AutofillGroup(
                    child: Column(
                      children: <Widget>[
                        TextFormField(
                          onChanged: (v) {
                            context.read<AuthFormBlocCubit>().changeEmail(v);
                          },
                          autofillHints: const [
                            AutofillHints.email,
                            AutofillHints.username,
                            AutofillHints.newUsername
                          ],
                          keyboardType: TextInputType.emailAddress,
                          decoration: InputDecoration(
                            hintText: "auth.form.email".tr(),
                            labelText: "auth.form.email".tr(),
                          ),
                        ),
                        const SizedBox(height: 16),
                        TextFormField(
                          onChanged: (v) {
                            context.read<AuthFormBlocCubit>().changePassword(v);
                          },
                          keyboardType: TextInputType.visiblePassword,
                          obscureText: true,
                          autofillHints: const [
                            AutofillHints.password,
                            AutofillHints.newPassword
                          ],
                          decoration: InputDecoration(
                            hintText: "auth.form.password".tr(),
                            labelText: "auth.form.password".tr(),
                          ),
                        ),
                        const SizedBox(height: 8),
                        const Spacer(),
                        CustomButton.fullWidth(
                          label: "auth.login.btn_enter".tr(),
                          onPressed: state.validLoginForm
                              ? () {
                                  context.read<UserBloc>().add(Login(
                                      state.email!.trim(),
                                      state.password!.trim()));
                                  TextInput.finishAutofillContext();
                                }
                              : null,
                        ),
                      ],
                    ),
                  );
                }),
              ),
            ),
          )),
    );
  }
}

Flutter doctor:

[✓] Flutter (Channel stable, 3.7.12, on macOS 13.0 22A380 darwin-arm64, locale en-US)
[✓] Android toolchain - develop for Android devices (Android SDK version 33.0.0)
[✓] Xcode - develop for iOS and macOS (Xcode 14.1)
[✓] Chrome - develop for the web
[✓] Android Studio (version 2021.2)
[✓] VS Code (version 1.80.2)
[✓] Connected device (3 available)
[✓] HTTP Host Availability

This is what I’m getting:

This is what I'm getting

This is my xcode setup

I’m missing the "save" popup after logging in:
Missing popup

Also, how can I make the suggestion work like this (instead of simple "Password" suggestion which I’m getting at the moment):
Desired suggestion format

2

Answers


  1. Try following this format. Replace your TextFormFields with TextFields. You need to pass controllers to each TextField.

    @override
      Widget build(BuildContext context) {
        return AutofillGroup(
          child: Column(
            children: <Widget>[
              TextField(controller: username, autofillHints: [AutofillHints.username]),
              Checkbox(
                value: isNewUser,
                onChanged: (bool newValue) {
                  setState(() { isNewUser = newValue; });
                },
              ),
              if (isNewUser) TextField(controller: newPassword, autofillHints: [AutofillHints.newPassword]),
              if (isNewUser) TextField(controller: repeatNewPassword, autofillHints: [AutofillHints.newPassword]),
              if (!isNewUser) TextField(controller: password, autofillHints: [AutofillHints.password]),
            ],
          ),
        );
      }
    

    For more info see the documentation.

    Login or Signup to reply.
  2. First, add the shared_preferences package to pubspec.yaml file:

    dependencies:
      shared_preferences: ^2.0.6
    

    next, import the package in widget where the user login info should be saved:

    import 'package:shared_preferences/shared_preferences.dart';
    

    Then, on login page, after successful log in, save details using the setString method from the SharedPreferences instance.

    SharedPreferences prefs = await SharedPreferences.getInstance();
    prefs.setString('email', state.email!.trim());
    prefs.setString('password', state.password!.trim());
    

    This will save the email and password on the device for future use. When app opens again, retrieve the saved data by using the getString method:

    SharedPreferences prefs = await SharedPreferences.getInstance();
    String email = prefs.getString('email');
    String password = prefs.getString('password');
    

    the method can also be used to set and retrieve other details, such as name or profile picture. Just make sure to store sensitive information, like password, using an encrypted format for security purposes.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search