libmx3 / mx3

a sample project showcasing/collecting cross platform techniques on mobile
MIT License
1.17k stars 146 forks source link

Noob: Integrate in to existing project? #61

Open wesselj1 opened 9 years ago

wesselj1 commented 9 years ago

Sorry for the very basic question. I like the idea of mx3 and would like to experiment with it for a POC for a client. If I already have two existing POCs completed for iOS and Android that I'd like to integrate this in to is there a way to do that or should I just build a new project and then reintegrate my UI code? I'm thinking the latter is the best way to go since the make would overwrite the current Android and iOS dirs?

skabbes commented 9 years ago

I'd start one layer at a time, using this as an example reference. For starters, I'd get djinni set up for some shared data classes. Then if you think that a cross platform build system is necessary, perhaps consider gyp - but for a proof of concept that might be overkill.

wesselj1 commented 9 years ago

I spent some time playing around with the example (iOS in particular) in order to familiarize myself a bit with the code, not to mention I haven't done C++ since one semester in college. C++ was my first language in high school, but that was about 8 years ago now, so I'm a bit behind on the C++ train.

Anywho, I was trying to expand on the example app by adding the user avatar to the UI. I've kind of stumbled a bit through the dark and got stuck, but I think I'm at least on the right track.

Firstly I added avatar_url: string to the view_model.djinni for the user_list_vm_cell. I reran make play. I than found some db lines in user_list_vm.cpp on the get_users callback. I modified those lines as follows: (++ on added/modified lines)

++ auto update_stmt = db->prepare("UPDATE 'github_users' SET 'login' = ?2, 'avatar_url' = ?3 WHERE 'id' = ?1;");
++ auto insert_stmt = db->prepare("INSERT INTO 'github_users' ('id', 'login', 'avatar_url') VALUES (?1, ?2, ?3);");
sqlite::TransactionStmts transaction_stmts {db};
sqlite::WriteTransaction guard {transaction_stmts};

for (const auto& user : users) {
     update_stmt->reset();
     update_stmt->bind(1, user.id);
     update_stmt->bind(2, user.login);
  ++ update_stmt->bind(3, user.avatar_url);
     if ( update_stmt->exec() == 0 ) {
          insert_stmt->reset();
          insert_stmt->bind(1, user.id);
          insert_stmt->bind(2, user.login);
       ++ insert_stmt->bind(3, user.avatar_url);
          insert_stmt->exec();
      }
}
guard.commit();

Also changed this line here to use the new initalizer:

optional<UserListVmCell>
UserListVm::get(int32_t index) {
    if (index < this->count()) {
        ++ return UserListVmCell {index, m_rows[index][0].string_value(), m_rows[index][1].string_value()};
    }
    return nullopt;
}

But with these code changes I then get errors from string_value() in value.cpp. If I print out m_string I just see an empty string, but there seems to be some other encoded data (?). And m_type is set to INT. I sort of just guess at m_rows[index][1] on the as I cannot po m_rows[index] or m_rows[index][1] to peek at the data. I've never tried to debug C++ in Xcode so I'm not sure if I'm doing something wrong. This might be part of the issue?

Thanks for looking at this stuff by the way. I'm sure you've plenty of other stuff on your plate.

skabbes commented 9 years ago

The class mx3::sqlite::Value is a bit of a weird one, I'll admit. What it is is a variant type which can hold, integers, strings, blobs, or doubles (since sqlite is actually dynamically typed). There is nothing magic that automatically converts ints to strings or anything (but it will automatically convert double to int ). So, the fact that m_type is INT means that you can't access it as a string. (I am actually very surprised that accessing m_string didn't throw an error for you).

Anyway, the root of your problem is what you thought was the avatar_url is actually the id. Check out this sql statement.

skabbes commented 9 years ago

What this really means, is that I need to get some docs up on the sqlite section of this code.

wesselj1 commented 9 years ago

Haha, okay. So which column would be the avatar_url? I was trying to verify it was being saved in the db. Since I could not po the rows I tried to look at the database but, of the 4 databases I see in the simulator's application data dir, kv.sqlite is just the demo username and the times ran, example.sqlite is empty with no table, and the other two db's I cannot open is SQLite Browser as it says they are not sqlite databases.

skabbes commented 9 years ago

change the select statment to be

"SELECT `login`, `id`, `avatar_url` FROM `github_users` ORDER BY id;"

Then you'll be able to access it as row[2].string_value() (since avatar_url is the third index).

wesselj1 commented 9 years ago

Ohhhhhhh. Dang it. Haha it's been a while since I've done much manual SQL statements. That makes total sense, not sure why I overlooked that. Thanks!

skabbes commented 9 years ago

ya, I want to find a good ORM-style thing to add in here, but at the same time I want the repo to be as simple as possible.

wesselj1 commented 9 years ago

Yeah I'm not against plain old SQLite statements, but some wrapper or other relational mapping would be nice. I haven't been in the C++ realm in some time so I've no idea what all is out there.