Skip to content

Commit

Permalink
Merge: iOS: implement data_store and missing life cycle callbacks
Browse files Browse the repository at this point in the history
Implement the main missing features of _app.nit_ on iOS: `data_store` and life-cycle hooks (like `on_save_state`). These changes can be seen on the calculator app, as it preserves its context using the `data_store`.

`data_store` is implemented with `NSUserDefaults` to store objects sertialized to Json. It is very similar to Android's implementation using shared preferences. This may be a bit limited as it is not meant to hold large strings, and some data objects (like game saves) should instead be saved to a file.

This PR also implements all life-cycle callbacks in iOS, until now only `on_create` was implemented. We may have to update _app.nit_ life-cycle to fit better with the life-cycle of iOS, the states between a running app and a fully stopped app are different between iOS and Android. I'm thinking of removing the two callbacks on_start/on_stop and keep only the more general callbacks on_create/on_destroy and on_resume/on_pause, and the services on_restore_state/on_save_state.

Pull-Request: #1947
Reviewed-by: Jean Privat <jean@pryen.org>
  • Loading branch information
privat committed Feb 12, 2016
2 parents 19c0a20 + 298a7aa commit acc18ca
Show file tree
Hide file tree
Showing 8 changed files with 116 additions and 22 deletions.
1 change: 1 addition & 0 deletions lib/app/data_store.nit
Expand Up @@ -26,6 +26,7 @@ import serialization
# TODO: move on the platform once qualified names are understand in the condition
import linux::data_store is conditional(linux)
import android::data_store is conditional(android)
import ios::data_store is conditional(ios)

redef class App
# Services to store and load data
Expand Down
14 changes: 6 additions & 8 deletions lib/binary/serialization.nit
Expand Up @@ -336,6 +336,12 @@ redef class Text

return true
end

redef fun serialize_to_binary(v)
do
v.stream.write_byte kind_string
v.stream.write_block to_s
end
end

# ---
Expand Down Expand Up @@ -397,14 +403,6 @@ redef class Char
end
end

redef class String
redef fun serialize_to_binary(v)
do
v.stream.write_byte kind_string
v.stream.write_block self
end
end

redef class NativeString
redef fun serialize_to_binary(v)
do
Expand Down
21 changes: 21 additions & 0 deletions lib/cocoa/foundation.nit
Expand Up @@ -149,3 +149,24 @@ extern class NSIndexPath in "ObjC" `{ NSIndexPath * `}
return [self indexAtPosition: position];
`}
end

# Interface to the defaults system for an app to customize its behavior to match a user's preferences
extern class NSUserDefaults in "ObjC" `{ NSUserDefaults * `}
super NSObject

# Wraps: `[NSUserDefaults standardUserDefaults]`
new standard_user_defaults in "ObjC" `{
return [NSUserDefaults standardUserDefaults];
`}

# Wraps: `[NSIndexPath stringForKey:]`
fun string_for_key(key: NSString): NSString in "ObjC" `{
return [self stringForKey: key];
`}

# Wraps: `[NSIndexPath setObject: forKey:]`
fun set_object(value: NSObject, default_name: NSString)
in "ObjC" `{
[self setObject:value forKey:default_name];
`}
end
32 changes: 24 additions & 8 deletions lib/ios/app.nit
Expand Up @@ -139,7 +139,12 @@ redef class App
# The application just launched but is not yet displayed to the user
#
# Redef this method to customize the behavior.
fun did_finish_launching_with_options: Bool do return true
fun did_finish_launching_with_options: Bool
do
on_create
on_restore_state
return true
end

# The application is about to move from active to inactive state
#
Expand All @@ -151,7 +156,7 @@ redef class App
# Redef this method to pause ongoing tasks, disable timers, and
# throttle down OpenGL ES frame rates. Games should use this
# method to pause.
fun will_resign_active do end
fun will_resign_active do on_pause

# The application just left foreground it can be suspended at any time
#
Expand All @@ -161,27 +166,38 @@ redef class App
#
# If your application supports background execution, this method
# is called instead of `will_terminate` when the user quits.
fun did_enter_background do end
fun did_enter_background
do
on_save_state
on_stop
end

# The application will enter the foreground
#
# Called as part of the transition from the background to the
# inactive state.
#
# Redef to und changes made on entering the background.
fun will_enter_foreground do end
# Redef to undo changes made on entering the background.
fun will_enter_foreground do on_start

# The application just became active
#
# Redef to restart any tasks that were paused (or not yet started) while
# the application was inactive. If the application was previously
# in the background, optionally refresh the user interface.
fun did_become_active do end
fun did_become_active do on_resume

# The application is about to terminate (not suspended)
# The application is about to terminate (from a state other than suspended)
#
# Redef to save data if appropriate.
fun will_terminate do end
fun will_terminate
do
# Usually a forced termination by the system
on_save_state
on_pause
on_stop
on_destroy
end
end

app.register_args(program_name.to_cstring, args.length, args)
Expand Down
60 changes: 60 additions & 0 deletions lib/ios/data_store.nit
@@ -0,0 +1,60 @@
# This file is part of NIT ( http://www.nitlanguage.org ).
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

# Implements `app::data_store` using `NSUserDefaults`
module data_store

import app::data_store
import cocoa::foundation
private import json::serialization

redef class App
redef var data_store = new UserDefaultView
end

private class UserDefaultView
super DataStore

# The `NSUserDefaults` used to implement `DataStore`
var user_defaults = new NSUserDefaults.standard_user_defaults is lazy

redef fun [](key)
do
var nsstr = user_defaults.string_for_key(key.to_nsstring)

if nsstr.address_is_null then return null

# TODO report errors
var deserializer = new JsonDeserializer(nsstr.to_s)
return deserializer.deserialize
end

redef fun []=(key, value)
do
var nsobject: NSString

if value == null then
nsobject = new NSString.nil
else
var serialized_string = new StringWriter
var serializer = new JsonSerializer(serialized_string)
serializer.serialize(value)

# TODO report errors
nsobject = serialized_string.to_s.to_nsstring
end

user_defaults.set_object(nsobject, key.to_nsstring)
end
end
2 changes: 1 addition & 1 deletion lib/ios/ui/ui.nit
Expand Up @@ -78,7 +78,7 @@ in "ObjC" `{
redef class App
redef fun did_finish_launching_with_options
do
on_create
super
window.native.make_key_and_visible
return true
end
Expand Down
6 changes: 2 additions & 4 deletions lib/json/serialization.nit
Expand Up @@ -466,6 +466,8 @@ redef class Text
end
return res
end

redef fun serialize_to_json(v) do v.stream.write(to_json)
end

redef class Serializable
Expand Down Expand Up @@ -534,10 +536,6 @@ redef class Char
end
end

redef class String
redef fun serialize_to_json(v) do v.stream.write(to_json)
end

redef class NativeString
redef fun serialize_to_json(v) do to_s.serialize_to_json(v)
end
Expand Down
2 changes: 1 addition & 1 deletion lib/serialization/serialization.nit
Expand Up @@ -221,7 +221,7 @@ redef class Char super DirectSerializable end
redef class Int super DirectSerializable end
redef class Float super DirectSerializable end
redef class NativeString super DirectSerializable end
redef class String super DirectSerializable end
redef class Text super DirectSerializable end
redef class SimpleCollection[E] super Serializable end
redef class Map[K, V] super Serializable end

Expand Down

0 comments on commit acc18ca

Please sign in to comment.