首选项保存数据时报错：Cannot read property putSync of undefined
====================================================

#### 问题现象

运行问题代码后闪退，日志如下：

Pid:8619
Uid:20020045
Reason:TypeError
Error name:TypeError
Error message:Cannot read property putSync of undefined
Stacktrace:
  at saveData (entry/src/main/ets/pages/Index.ets:71:5)
  at anonymous (entry/src/main/ets/pages/Index.ets:41:11)

问题代码示例参考如下：

_// index.ets_

import Prompt from '@system.prompt';
import { UIAbility } from '@kit.AbilityKit';
import { util } from '@kit.ArkTS';
import { BusinessError } from '@kit.BasicServicesKit';
import { window } from '@kit.ArkUI';
import preferences from '@ohos.data.preferences';

let dataPreferences:preferences.Preferences
class EntryAbility extends UIAbility{
  onWindowStageCreate(windowStage: window.WindowStage) {
    let options: preferences.Options \= { name: 'myStore' };
    dataPreferences \= preferences.getPreferencesSync(this.context, options);
  }
}
@Entry
@Component
struct Index {
  @State inputText: string \= '';
  @State savedText: string \= '这里将显示保存的内容';

  build() {
    Column() {
     _ // 输入框_
      TextInput({ placeholder: '请输入要保存的内容' })
        .width('90%')
        .height(60)
        .onChange((value: string) \=\> {
          this.inputText \= value;
        })

      _//_ _保存按钮_
      Button('保存数据')
        .width('90%')
        .height(60)
        .margin({ top: 20 })
        .onClick(() \=\> {
          this.saveData();
        })

   _   // 显示保存内容的按钮_
      Button('显示保存内容')
        .width('90%')
        .height(60)
        .margin({ top: 20 })
        .onClick(() \=\> {
          this.loadData();
        })

   _   // 显示保存内容的文本区域_
      Text(this.savedText)
        .width('90%')
        .margin({ top: 20 })
        .fontSize(20)
        .textAlign(TextAlign.Center)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }

  _// 保存数据到Preferences_
  private saveData() {
    if(this.inputText \== null){
      Prompt.showToast({message: '内容为空请重试'})
      return
    }
    dataPreferences.putSync('my',this.inputText);
    dataPreferences.flush()
  }

  _// 从Preferences加载数据_
  private loadData() {
    let get\_text \= dataPreferences.getSync('my','6666')
    this.savedText \= get\_text.toString()
  }
}

#### 背景知识

*   [通过用户首选项实现数据持久化](https://developer.huawei.com/consumer/cn/doc/harmonyos-guides/data-persistence-by-preferences)：用户首选项(Preferences)为应用提供Key-Value键值型的数据处理能力，支持应用持久化轻量级数据，并对其修改和查询。
*   首选项实例可见[demo](https://gitee.com/harmonyos_samples/preferences)。

#### 问题定位

1.  根据报错信息‘Cannot read property putSync of undefined’和报错代码行‘at saveData (entry/src/main/ets/pages/Index.ets:71:5)’，可定位至saveData()方法中的putSync属性未找到。
2.  putSync是dataPreferences的方法，dataPreferences的实例化是在class文件entryAbility进行调用的。检查代码后发现主程序没有关于entryAbility的调用链，即dataPreferences未实例化。

#### 分析结论

dataPreferences未实例化导致报错。

#### 修改建议

在主程序中添加异步方法aboutToAppear()方法，并在里面进行Preferences实例化：

import { promptAction } from '@kit.ArkUI';
import preferences from '@ohos.data.preferences';

let dataPreferences:preferences.Preferences;

@Entry
@Component
struct Index {
  @State inputText: string \= '';
  @State savedText: string \= '这里将显示保存的内容';

  async aboutToAppear() {
    let context \= this.getUIContext().getHostContext() as Context;
    let options: preferences.Options \= { name: 'myStore' };
    dataPreferences \= preferences.getPreferencesSync(context, options);
  }

  build() {
    Column() {
     _ // 输入框_
      TextInput({ placeholder: '请输入要保存的内容' })
        .width('90%')
        .height(60)
        .onChange((value: string) \=\> {
          this.inputText \= value;
        })

 _     // 保存按钮_
      Button('保存数据')
        .width('90%')
        .height(60)
        .margin({ top: 20 })
        .onClick(() \=\> {
          this.saveData();
        })

     _ // 显示保存内容的按钮_
      Button('显示保存内容')
        .width('90%')
        .height(60)
        .margin({ top: 20 })
        .onClick(() \=\> {
          this.loadData();
        })

    _  // 显示保存内容的文本区域_
      Text(this.savedText)
        .width('90%')
        .margin({ top: 20 })
        .fontSize(20)
        .textAlign(TextAlign.Center)
    }
    .width('100%')
    .height('100%')
    .justifyContent(FlexAlign.Center)
  }

  _// 保存数据到Preferences_
  private saveData() {
    if (this.inputText \== null) {
      promptAction.openToast({ message: '内容为空请重试' });
      return;
    }
    dataPreferences.putSync('my', this.inputText);
    dataPreferences.flush();
  }

 _ // 从Preferences加载数据_
  private loadData() {
    let get\_text \= dataPreferences.getSync('my', '6666');
    this.savedText \= get\_text.toString();
  }
}

#### 常见FAQ

Q：dataPreferences存储后的文件路径在哪里？

A：dataPreferences实际上是一个xml文件，位置放在data/app/el2/100/base/<包名>/haps/entry/preferences目录下。可以在IDE右下角，点击Device File Browser，找到文件路径。