Tag Archive: iOS


Today was another sort of short impromptu meeting where I just sort of caught up with Evan about some of the new issues resulting from this afternoon’s test by Digimarc. One of the big issues resulting from that was that apparently the new version of Pellet is hating on our ontologies, resulting in all of the reasoning breaking down. Sort of bad. The rollback to an older version of Pellet fixed this but also broke a bunch of the other libraries until they too were updated.

Another change that Evan did was to initialize some test data for the recommendation manager. This means that one of my changes from a while ago to the View Recommendations controller could now be tested. To my surprise, it actually displayed the recommendation!

There are still some issues with it because I adapted another class to list the recommendations, resulting in it trying to find linked recommendations when an item is clicked. Since this is its own view right now, there isn’t actually anything to pull recommendations from, in connection to, so it fails. Interestingly, this can be resolved by simply viewing a restaurant menu. This causes the server to pull in the restaurant data which the recommendation view can now compare against, and results will appear if an item is clicked.

Of course, this in turn led to another server-side issue because the restaurant data being pulled isn’t actually cleared after leaving the restaurant view. This means that if multiple menus are viewed, the total union of items being compared against just keeps growing. Although not screenshotted, a test with this managed to get a listing of both the test item, the items for a previously viewed restaurant, and items from the currently viewed restaurant.

There was also a weird bug where the Is A for the item showed a blank node instead of the item name. Server explosions all around, but luckily nothing that crashes the application right now (after a round of fixes, anyhow).

After testing with the recommendation view, I went back to fiddling with some bugs with the login screen that were encountered during the test. One issue was that during the test, Evan noticed a null session being passed all of a sudden, which isn’t very noticeable right now, but needs to be addressed. We looked through the code for a while, and Evan realized that the reason was probably that the tester switched from their iPad to the iPhone, but had the same data synced to both through iTunes. This meant that the keychain had a cached login but no session ID, since that is separate, and so ‘logged in’ without one.

Another issue was that if the user hits log out then terminates the program, they still seem to be logged in when they start up again. Since this was something I was sure I had addressed, I went searching through the code, placing a bunch of NSLogs around. Finally, I noticed that Evan had changed the getter of theUser to automatically initialize it if it is nil. Since I had based the login scheme around comparisons of the current User singleton with nil, this sort of broke my code. Unfortunately, he had made this change because of a crash resulting BECAUSE the User could be nil at the start. Oops!

I resolved this by changing my login scheme to check, not for a nil User, but for a User with a nil session ID. This is also a change that will also be consistent with the fix to the other session ID problem.

That fix for session ID will involve setting up a verification system for the session ID, where the program needs to grab a session ID if it is nil but they have a user login cached, or verify that their current session ID is valid, since the server may have restarted and lost all of the session data.

Advertisements

Today was a sort of impromptu meeting with Evan to finally finish the rest of the issues with the login screen. This was a lot faster than usual since we were both there and able to debug on both the client and server sides, whereas on my own I usually have to wait to find Evan and let him know what issues were appearing on the client side due to issues with talking to the server and he would eventually fiddle with it on his end.

While Evan fiddled with getting the create user command to actually function on the server side, I fiddled with the interface so I wouldn’t disturb the implementation changes he was doing. I removed the obsolete iPhone link option and realigned everything else to fit again.

We also fixed it so that the return button no longer needed to be clicked to actually update the field. This was due to a misunderstanding when I initially did it, where I had the processing inside of the textFieldShouldReturn function.

As it turns out, this function is really only meant to return the behavior when the return button is actually pressed, not when the input itself is just returned. The code was simply moved into the actual cell generation code, so that it will be called anytime the field returns and updates the cell.

Another change within both the UI and implementation was changing all of the fields so that all user data can be entered. This was part of a whole explosion of changes to both the server and client to resolve the many issues.

For example, there was a disconnect between the passwords being sent and received, because of differences in the encryption and decryption methods.

With all of those and other issues out of the way, the login and create user functionality is finally complete with the network communications now working and necessary.

After this was another big chunk of time spent looking at how the iOS keychain works. We needed to use this in order to store the user’s authenticated information so that they won’t have to login every single time they start up the Wine Agent.

In the User tab, you might remember the two functionless options for linking and logging out. I removed the linking option since its login page counterpart has also been removed.

The logging out simply performs a reverse of the keychain manipulation, removing the user’s entry and regenerating the modal login screen over itself.

After all of that was done, I went back and tested the functions a lot more thoroughly, trying to find all of the corner cases we might have missed and fix them.

One of these was that if the user or password fields were blank, the application would crash due to manipulation of the strings within the conversions before the network communication. A blank string would turn into a null object when translated into the network compatible string, and so an access error would result in the commdelegate.

This was easy to fix by adding an error message about it.

Another annoying issue I ran into was how the text fields for everything kept trying to autocorrect everything, with capitalization. This was resolved by simply changing the autocorrection property of the text field. (text.autocorrectionType = UITextAutocorrectionTypeNo;)

The last major issue that I found was where an invalid login would make all future ones invalid as well, even if it should have been valid. The responses were as expected, but the processing was somehow going wrong.

I immediately suspected that it was caching the previous entry of the fields or the invalid response somewhere, and tried to do testing to figure out which one.

To see if it was the first, I tried to use blank or cleared fields as well as additional clearing of the fields to be sure that nothing was being cached, but this didn’t seem to help.

More suspicious was the OWLInstance, since it caused so many problems before. However, I tried to test this by releasing it after each attempt, which had no effect.

At this point I went back to Evan to try to see what he thought. After a whole lot of breakpointing and stepping through everything, we figured out that it was, in fact, due to the OWLInstance not clearing itself properly.

My check hadn’t discovered this because although it was releasing the individual instance object, it was not clearing the singleton dictionary that actually holds all of the instance data.

Finally, we got it so that the previous responses are cleared each time, and the login interface is now completely fixed, including all of the corner cases that I could think of.

The only remaining issue related to the login screen is that the Personal Info is yet again incomplete, as the login of the user only writes the username and password to the object, not the first name, last name, foaf file, or e-mail.

Next will either be fixing up Personal Info again or going back to taking a look at View Recommendations.

I’m still working on the communication from the login/create user functions. I added all of the CommDelegate calls for both of the screens, but issues continue to pop up. Unfortunately, no screenshots since all of the work this time was nonvisible (and still not done).

During last week’s meeting, I had talked with Evan about my approach to try to get the response data back from the server, and I left thinking that once I added the reading of the parsed response data into the OWLInstance object, I would be able to quickly clean up the rest of the functionality.

Unfortunately, the curse of network communication still hates me.

After adding all of the CommDelegate calls and placing a bunch of NSLogs around to try to figure out what response I was getting, I was disappointed to find out that it was apparently returning nothing in the OWLInstance object.

I began to step through the code carefully, thinking that there were just some mistaken calls to the wrong parser. After fixing these, it still didn’t work, and after continuing to step through everything I finally realized that the parser itself…didn’t actually save anything. The populate function meant to send all of the parsed data out to the OWL objects didn’t have anything in it.

It took me a while to fix this, beginning by trying to base it off the old parser, before seeing that I could just reuse another part of the new parser as the base. As it turns out, I should have just gone the lazy route and copy/pasted it, but I went and overthought why they were different functions. Oops.

Finally, I had it so that the OWLInstance was retrieving the response from the server correctly. Unfortunately, my original curse of network communication still holds, and I get command errors from the create user communication and errors logging in because I can’t create a user.

The creating of the user was apparently due to the server software being out of date, so after that gets fixed I should be able to get everything working…finally. I’ll just need to set up the checking for the appropriate responses and build in the behaviors for both when the login screen should dismiss itself and getting the login data to write into the user object.

Worked a bit more on the login screen today, after installing the new Xcode 4. I was kind of worried at first, when I started it up it kept crashing, but it worked fine after a few tries so I think it was just having issues trying to reopen some of the files and such before it adjusted or something. The middle window seems to have vanished, at least from the default view, which was kind of weird since I’m used to that, but using the more organized tree sidebar is probably better anyhow.

Some interesting things I noted was that gdb automatically opens, as well as some stack info, which is pretty useful since the way I arrange my screen the gdb button used to be covered, and also happens to leave the new gdb window in a spot that’s easy to read. Another thing I like is how the build and run errors now load in the sidebar instead of in another window. All of these changes seem to work together to keep everything in the single window so I have less windows open at once, which is really helpful, both in working and in getting back to work next time.

So the first thing I did was to finish up some of the layout stuff, resizing it to a more squarelike version like I said I wanted to try. I had hoped to get a similarly neat effect that the modal windows have, without actually doing it as a sheet modal view, and it worked, I think. Also note that I finally got the iPhone link thing to be placed nicely.

Continuing, I worked on the login functionality, which started off with a mysterious crash with the LoginCommDelegate. Using breakpoints, I narrowed down the access error to what seemed to be between two functions, where the breakpoint was reaching the end of one but crashing before it got to the other one somehow. This turned out to be an issue with a double release on a string. I didn’t notice this because the first release was actually within one of the calls to NSString, which used an autorelease on its result.

This didn’t actually result in any real functionality yet, and I still need to implement the actual setting of the user object upon a successful login (as well as preventing a login if the server response shows it failed). However, to do this I need to see what the results are like so I can figure out what the response looks like to know what to pull out of the response into the user object.

Since I am still having issues with the network, I’ll probably look at this with Evan on Wednesday. The network has always been a big problem for me, since it means I can’t test a lot of things successfully like this.

Since I couldn’t get any further with the login functionality, I switched gears and worked on the counterpart user creation functionality. I adapted my work from creating the personal info page to implement the controller for this, and also generated it as a sheet modal view over the login full-screen modal view. You can see from the screenshot how it’ll work.

Along with these changes, I linked both the personal info edit screen as well as this user creation screen to the same singleton user object for the application, and will incorporate the login to this as well. This will keep the user’s information consistent between them.

The main issue is that none of the three functions actually have any network communication right now, since I’ve been having problems with that. This means that although all of the functions appear to work, they can’t create a permanent account for the user nor can it actually authenticate the user’s login right now.

Currently, the login screen lets the user in no matter what they put in, and it doesn’t write the login data to the user object since I want to get this working ASAP and didn’t bother with the dummy stuff since I’ll have to remove it later anyhow. Once I get the network working, I’ll have to do the user object initialization off the response.

The user creation actually does initialize the user object, so that later uses of the personal info window can edit it correctly. This will just need the addition of the network communication later, with a note to the user if it doesn’t go through that they are on a temporary account.

One thing that will have to be decided is whether the user creation automatically logs them in with that info, or just makes the account but makes the user have to login with it before letting them in. Currently it just appears to let the user in, and I think this will be how the complete version will work too. Less clicks makes for happier users, and there’s no real reason to do it otherwise that I can think of.

Will hopefully get the network stuff done on Wednesday, and with the integration of that the login screen will be complete. Oh! Except that iPhone link thing, I STILL have no idea what that thing is for. Another thing to talk to Evan about.

Although I began today’s work by doing some work on the functionality for the buttons, I decided that I should get the layout itself working first, since in a pinch we can still use the dummy user object, even if the functions are still in-progress. This also means that I won’t have to keep remembering to disable the code every time I commit, since the layout was crashing.

I quickly realized that the login screen would never fit nicely into a horizontal orientation on the iPhone, so I locked the rotation on those devices to just portrait orientations. It can still rotate upside down for those though. For the iPad, I needed to start figuring out how to get it to look good on the bigger screen, which meant doing some resizing work.

I’ve had issues with resizing before, with the multi-cell view, and I had solved it at the time using a whole load of conditionals and hardcoded values. This time, I wrestled with it in a different way, trying to utilize some automatic methods which I hadn’t been able to get working previously. Eventually, I managed to use the autoresizingMask and autoResizesViews properties to get some automatic layout fixes even through rotation. Ironically, it doesn’t really resize that much yet, but it is still much improved to before, as you can see.

I spent a while fiddling with autoresizingMask, testing various restrictions on how the resizing works. I ended up using UIViewAutoresizingFlexibleLeftMargin and UIViewAutoresizingFlexibleRightMargin in conjunction to get an automatic recentering. I played around with the top and bottom margins, because a centering would be nice vertically as well, but it appeared to force each element to space out, which made it look awful.

Some issues remaining are how the version and iPhone link elements are skewed. I’m pretty sure that this is because they are the only elements that didn’t start with a centered location. This means that the subsequent automatic resizing/repositioning is skewing it to match the iPad screen.

I tried to fix the vertical centering by editing the bounds for the view, but the bounds settings appeared to be ignored, no matter how I went about it. As I recall, problems with this were one of the reasons I ended up with such an ugly solution for the multi-view cell. I ended up doing a similar thing here, with a vertical adjustor variable. However, instead of being purely hard-coded, I based it on the center of the view itself, and I definitely want to fix this later. It isn’t a perfect solution, as it is not perfectly centered when rotated, since the adjustor doesn’t actually…adjust automatically. Again, still a work in progress.

Next I need to play around with the actual resizing aspect. I’m thinking of trying for a more square-shaped interface on the iPad, because it would be more like the sheet modal view (though this is a full-screen modal view). Hoping for the same kind of cleanness that sort of view has. I also need to fix that vertical centering.

Finally, after that’s all set up I need to put in the functionality itself. I spent a while thinking about how to do this, and I think it’ll be done in stages, so that it has some sort of pseudo-functionality at each stage until it’s fully working.

For the login fields/button, I’ll start by having it set the singleton user object with the given fields, without any actual server communication. This won’t be a real “login”, but will let the application feel like it is, with the password editable in personal info (username isn’t editable), even though it isn’t persistent. After this will be the actual implementation of the server communication for login, with the associated success and fail cases.

The create user button will be the same, starting with a very similar screen to the personal info screen, where the username, password, and other information can be input. The first version will simply write this to the user object, like before, allowing for the appearance of the full functionality (within a session). The second will have to do the server communication and processing.

I’m not actually sure what the iPhone link thing is supposed to do, functionally, so that’ll be included last.

The world’s lamest screenshot below! There’s a point…really!

I haven’t updated in a while, been swamped by a bunch of projects and take-home exams. I started out today working on the View Recommendations feature, trying to figure out how it would work and how to go forward. I made the view itself and ended up linking it to the (in-progress) recommendation manager, which I believe will eventually hold all of the recommendation information and will also handle the communications with the server for them. Unfortunately, it doesn’t actually show anything right now since the manager itself is not fully implemented right now.

During the Wine Agent meeting Evan seemed sort of confused about why it was marked as critical (which is why I started working on it) and suggested that I work on the login screen instead. Since I had been thinking of doing that in the first place, only choosing otherwise due to the recommendations view being marked as critical, I immediately switched over. The login screen was the logical next step after the sort of finished personal info page, since that will only have real functionality once the global user object is actually enforced and initialized at the start (if not already logged in).

First was deciding how to implement the login screen, as in where and when it should force the user to login or register as a new user. I began thinking that this would be done as a full-screen modal view that appears upon application startup if the user object is nil. However, I began working on this thinking I would be able to call it from the application startup loop, which failed since it cannot present a modal controller from itself.

I ended up messing up a few more times before finally setting up the user object check in the application startup, and if the user object is nil then it will set the starting tab to the User one. This part will be temporary, since I will eventually want to allow the application to load the tabs exactly the same way as it usually does depending on where the user was last, but for simplicity in implementing the modal popup I did it this way. Once I get it all finalized then I can go through and add the delegate capabilities for presenting and dismissing the modal view to everything, I suppose. Unless it could be any view, which would be painfully tedious and hard to maintain. I’ll need to do some testing on which pages can actually be accessed upon startup.

Anyhow, once I had it defaulted to the single user screen if the user object was nil, I implemented the actual presentation of the login view controller in a modal view. This screen will probably be mostly or completely redone, but you can see what the old login screen used to look like in the screenshot. It crashed for a while due to bad memory accesses, but they were eventually sorted out.

The next step will be figuring out how to reimplement the UI itself so that it fits on all the devices and also functions (it crashes currently whenever I try to hit any of the buttons).

This post actually covers all the work since the last update, since I’ve been more focused on the actual work than writing up the post. Sorry about that, but at least I remembered to take screenshots this time!

The first step was creating and setting up the actual user object, which was fairly simple. We already had a User class so it was a simple matter of altering it, adding an instance to the personal info view controller, and adding some code so it correctly displays the current data as part of the options.

I began working on the next part, which was to add the edit functionality to each button. I had originally intended to do this by having each button bring up a keyboard, whose results would become the new data associated with that button. However, after talking with Evan we ended up editing this plan drastically. The new plan calls for several changes. In terms of the areas being displayed and edited, we need to have the first and last names be editable, instead of the username, which will be constant.

Also, instead of having it be an additional view on the existing navigation controller, it will be done via a modal controller. This change was the first that I did, since I have done similar changes before and knew what I needed to do. You can see in the screenshot that there is a done and reset button. Depending on how the data moves, I may have it set so that the reset button can restore the original values of each button. This would assume that the modal data is not committed to the actual user object until the done button is pressed. On the other hand, if we simply have every edit change the user object, then this reset button will be removed, and the done button may be reworded to Back to prevent confusion about this.

Finally, instead of having the current value on the right side of the cell, Evan wanted me to match some of the other cells in the application by having an editable text subview in the middle of the cell that has the current value defaulted to it. This subview will bring up the keyboard when pressed, which will edit that value. In the screenshot you can see that I have been trying to implement this on the username, but have not had any success.

Eventually, I figured out that it was stemming from an error I had made in the initialization checks, where I had actually made the case for when the subview already existed, but forgotten to make it in the first place, and was able to get the text field instead of the read-only subtitle thing. With that done with, I went ahead and changed the username to first name and last name to match that part of the design change and extended the text field change to all four areas.

The next part was to get the field to actually do something. I ran into several issues here, because the delegate function called from the text field just has the text field as an argument, without any reference to which text field it actually is. I eventually resolved this after playing around with the text field tags, which involved several small oops moments where I had to wrestle with NSLog and some silly things where I was thinking way too hard about how to get from the textfield to the cell view, before remembering that I had already set tags. With a few tweaks to make sure each option gets its own unique tag and some test outputs, I had an easy way to identify each text field.

From there, it was just a matter of setting up some conditionals and writing to the user object.

One interesting note about the behavior that I haven’t figured out if it is required is the fact that the user must hit Return before it actually saves the new data to the object. This is due to how the delegate function is called, and I don’t see any immediate solution if we want to do this differently.

Also, the personal info has a similar issue as the preferences where the data is not persistent across runs. Within a single run it does persist, however, as seen in the screenshot where the previous screenshot’s edit has taken hold and is now the initial displayed value.

I also removed the reset button, since each edit affects the user object directly (and so there is no way TO reset currently…although if you hit Done without hitting return it won’t save and so this is an indirect way of getting that behavior!).

And yes, I did get the password to work the way I wanted, where it always displays it as the right number of * for the password, without displaying it. I was amused the first time I tested it because I entered some gibberish and iOS tried to autocorrect it and got Cthulhu.

Today I began my usual planning and preliminary work on the next section I’m working on, the personal info view. This view will eventually allow the user to change their username, e-mail, and password. Of course, that will need the login screen to actually be reactivated, so that there is something to change!

As part of the planning, I basically just looked at the existing classes to try to see how the user information itself is going to work. I know that at some point we will be reactivating the login screen. As such, I tried to look to see if there were any existing objects containing the user information. Although there appears to be such a user class, as well as a login class, I did not see any actual instances, which will likely be created for the application when we reactivate the login screen. This means I will likely create this personal info page with a dummy user at first, until I can integrate it later with the login screen.

Knowing that, I started to think about how the layout was going to look like. The screenshot shows an initial creation of the view, though I am debating about whether to do it in 3 sections or just the one. If I keep the current layout, the current data will be displayed on the right side as the second information block on the button, and clicking the button will bring up a screen where the information can be edited via keyboard.

The next part is to create the dummy object and figure out how the edit screens will work.

Hm, forgot to post this yesterday. The last two days were spent fixing up the last of the previous changes and finalizing that they work, the preferences section. One thing that had not been done in the last iteration on them was making each area editable. This was fairly straightforward, where I just had to set up the initialization to take the existing data and start up that way. It got a little bit more complicated when returning, where it would add it, but would also need to remove the old entry.

My initial attempt to do this seemed to work, but caused several odd issues with areas seeming to disappear because of when I was removing cells and reloading the table. Fixing this did not remove all of the bugs, and also showed me another bug where it would remove the cell even if a new one was not added, such as if I simply cancelled the edit window. To fix both issues, I reworked when I was removing it to only happen on return, with conditionals for both cancelled and completed generators.

After getting this to work for the simpler food and wine preferences, it was pretty easy to extend my changes to the recommendation preferences as well. After fixing that, making sure it works on both devices, and fiddling with the timing to make the transition smoother, the preferences looks good now.

Another issue that popped up was from Evan’s testing, where he is currently working on a new split view of the menus, which has been floating around for a while but is finally being implemented (a week before it needs to be shown, no less). Because of the incredibly annoying way the multi-cell view does not receive the autoadjust, it had to be tweaked carefully for each orientation on each device, using a series of conditionals. All of this is further complicated by the new layout, which introduces yet another view on top of it as well as a different view size to boot. Basically, it all broke again. Evan said he would take a look at it, because he wanted me to focus on the next area, which is to create a Personal Info view, where the user should be able to view and modify their username, e-mail, and password.

Trying to quickly finish the existing issues with the multicell displays and preferences stuff so I can get started on the new tasks. The multi-cell work went fine, which is probably because I’ve gone to war against it so many times that I’ve pretty much memorized which issue, section of code, and fix is needed for each error. Just needed to resize it on iPad, because it worked on iPhone, which is probably what made it slip past me the first time. The menu view had some additional rotation issues where there were really weird resizing issues when coming back from the Twitter window, but I had already encountered the same type of problem before and quickly fixed that up.

Hoping to look at Preferences tonight/tomorrow, where I need to make the various options editable and also do a final check of everything to make sure no lingering bugs are around. Wednesdays are always unpredictable because I have unpredictably long meetings for my SD&D project and I still need to finish up some other assignments for Friday, so we’ll see how it works out.

Today’s All-Hands meeting was interesting, although most of it didn’t really apply to me such as budgeting and travel changes. They are moving them to a monthly meeting because they felt that the time wasn’t really being used well, what with people reading e-mail and such. I admit that I was actually working on Wine Agent during the meeting, but I was paying attention! They’re going to try to have status updates from everyone at that time as well. My only thought about the idea was that it seems like the meeting is going to overload now. It will take time for everyone to give their update, and then I assume that presentations will all be compacted as well, but I guess we can’t know unless we try it out.