Pregunta

Fondo

  • Tengo una NSOutlineView que muestra TrainingGroup entidades.

  • Cada TrainingGroup representa una carpeta en el equipo local.

  • El NSOutlineView se une a un NSTreeController con un predicado ha podido recuperar de IsTrained == 0

  • Cada TrainingGroup se puede asignar a un proyecto.

  • Cada TrainingGroup tiene muchas TrainingEntries que muestran un tiempo trabajó en ese archivo.

  • Cuando se asigna el TrainingGroup a un proyecto, el IsTrained se establece en YES.

  • En Asignar a un proyecto, todos los descendientes son también asignó a ese proyecto y de sus bienes IsTrained se establece en YES también.

  • Proyecto columna se une a la propiedad projectTopLevel.

Ejemplo

Todo el aspecto de árbol como este:

Name                       Project              IsTrained
Users                      nil                  NO
  John                     nil                  NO              
    Documents              nil                  NO
      Acme Project         Acme Project         YES
        Proposal.doc       Acme Project         YES
          12:32-12:33      Acme Project         YES
          13:11-13:33      Acme Project         YES
          ... etc
        Budget.xls         Acme Project         YES
      Big Co Project       Big Co Project       YES
        Deadlines.txt      Big Co Project       YES
        Spec.doc           Big Co Project       YES
      New Project          nil                  NO
        StartingUp.doc     nil                  NO
      Personal Stuff       Personal             YES
        MyTreehouse.doc    Personal             YES
    Movies                 nil                  NO
      Aliens.mov           nil                  NO
      StepMom.mov          nil                  NO

Y el NSOutlineView sólo se vería así:

Users                      nil                  NO
  John                     nil                  NO              
    Documents              nil                  NO
      New Project          nil                  NO
        StartingUp.doc     nil                  NO
    Movies                 nil                  NO
      Aliens.mov           nil                  NO
      StepMom.mov          nil                  NO

Si ha asignado Películas de personal, la vista sería ahora el siguiente aspecto:

Users                      nil                  NO
  John                     nil                  NO              
    Documents              nil                  NO
      New Project          nil                  NO
        StartingUp.doc     nil                  NO

Código

TrainingGroup.m

-(void)setProjectTopLevel:(JGProject *)projectToAssign {
    [self setProjectForSelf:projectToAssign];
    [self setProjectForChildren:projectToAssign];
}

-(void)setProjectForSelf:(JGProject *)projectToAssign {
    [self setProject:projectToAssign];
}

-(void)setProjectForChildren:(JGProject *)projectToAssign {
    for (TrainingGroup *thisTrainingGroup in [self descendants]) {
        [thisTrainingGroup setProject:projectToAssign];
        if(projectToAssign != nil) {
            [thisTrainingGroup setIsTrainedValue:YES];
        } else {
            [thisTrainingGroup setIsTrainedValue:NO];
        }
        // Other code updating rules.
    }
}

-(JGProject *)projectTopLevel {
    return [self project];
}

-(NSSet *)untrainedChildren {
    // Code that loops through all children returning those
    // whose isTrained is NO. Omitted for brevity.
}

El problema

Como se puede ver arriba, estoy corriendo todo el código de asignación del proyecto en el hilo principal actualmente.

Cuando hay cientos de entradas de tiempo dentro de cada carpeta, mi aplicación deja de responder.

Posibles soluciones

1 Modal barra de progreso

El enfoque

  • Ejecutar asignación del proyecto en un subproceso en segundo plano en el contexto separado.
  • combinación de datos básicos del uso estándar en contexto principal cuando haya terminado.
  • bloques A hoja modales cualquier actividad adicional hasta que la asignación proyecto ha terminado.

The Good

  • El usuario recibe información inmediata sobre lo que está sucediendo.
  • La aplicación sigue siendo sensible.

The Bad

  • El usuario no puede hacer nada hasta que la asignación actual ha terminado.

2 no Modal Spinner

El enfoque

  • Ejecutar asignación del proyecto en un subproceso en segundo plano en el contexto separado.
  • combinación de datos básicos del uso estándar en contexto principal cuando haya terminado.
  • Mostrar el progreso spinner junto grupo de entrenamiento, lo que indica que está ocupado.
  • sobre la asignación de meta, el grupo de entrenamiento desaparece de la vista.

The Good

  • se está procesando, el usuario puede hacer otras cosas mientras que su última acción
  • La aplicación sigue siendo sensible. Un poco. Véase más abajo.

The Bad

  • En las pruebas, he visto una congelación de hasta 3 segundos cuando el contexto de fondo se fusiona en el marco principal.
  • La vista podría actualizar en el medio del usuario haciendo otra cosa, lo que podría ser molesto.
  • Deshacer sería difícil de implementar.

3 Ocultar

El enfoque

  • arriba, excepto el grupo de entrenamiento se retira en Asignar, y está dispuesto a ser "en curso" hasta que haya terminado de asignar.

Bueno y Malo

  • Igual que el anterior, excepto en el orden de los grupos de entrenamiento permanecería predicatable.
  • Todavía grande congelación en la parte posterior de combinación en contexto principal.

4 Mejorar el rendimiento

El enfoque

  • Mantenga el código tal como es, se ejecuta en el hilo principal.
  • Mejorar el rendimiento por lo que incluso con miles de entradas, la vista sólo se congela durante medio segundo como máximo

The Good

  • Aplicación sigue siendo sensible.
  • Deshacer, sigue siendo fácil.
  • Arquitectura sigue siendo sencilla.

The Bad

  • A mi entender, en contra de las recomendaciones de Apple - procesamiento intensivo no se debe hacer en el hilo principal
  • ¿Puedo conseguir el suficiente rendimiento bueno? Desconocido.

Mis preguntas

Hasta donde puedo ver, ninguna de las opciones anteriores son ideales.

1. ¿Cuál es la mejor opción?

2. ¿Hay otras opciones?

3. ¿Qué podía mejorar mi enfoque?

¿Fue útil?

Solución

  1. I actualizaría en un subproceso en segundo plano (Nº 2)
  2. Se puede desactivar la entrada del usuario siempre en las secciones de la ventana, y mostrar un mensaje de carga.
  3. Fácil de decir - ir a través de todo el código, y asegúrese de que está haciendo el menor número de llamadas necesarias, y que no se llama a las funciones innecesarias. También puede ejecutar algunas operaciones de larga duración en hilos separados, y luego ser notificado cuando termina de acción, por lo que puede procesar otras cosas mientras que la operación continúa.
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top