Archive for January, 2011

We had the first meeting of the semester for everyone working on the Mobile Wine Agent, which is Evan, Dan, Momo, and myself. We basically just spent the time talking about another important feature we need, which is the ability for group collaboration via Bluetooth. Although the recommendations and preferences themselves are still under construction, once they are complete it will be essential that group features be available.

The plan is basically to set it up so that any users of the application will be able to start a group recommendation, connect with their companions, and share their preferences/recommendations in order to (hopefully) get a result back that everyone will agree on, based on them. This will be done via Bluetooth so that this connection can be done locally (and the reasoning) so that the feature will not be limited by WiFi access or a connection to the server (though the iPhone/iPad are both still limited to server reasoning currently…which I still can’t connect to for my own testing, ironically enough).

The general outline of how this will work was drawn out. There needs to be functions/calls between devices corresponding to adding/removing/querying data and for the final result from the device’s reasoner. We hope the devices will be able to update each other on the user’s data, querying them to check things, and get a solution.

Of course, the details are still largely fuzzy, as this was just a general planning meeting, before any of us even looked at the feasibility. We tried to come up with issues we may have missed, such as a few involving multiple devices and their connectivity (or lack thereof) as related to reasoning and the major issues we will likely run into with the Bluetooth API/protocol itself, such as the data formats we can send, and whether we will be able to have interdevice functionality between the Android/iPhone/iPad versions.

As for feasibility, I spent a while looking this up afterwards, trying to find more information on the iOS Bluetooth API, what it would allow to be transmitted, a bit on how that works so I could think about implementation, and whether iOS to Android connections would even be possible.

The results upon searching for an iOS Bluetooth API seemed unfortunate at first, with almost every result being someone asking whether it even existed. More outdated results either said no or mentioned that it only applied to audio, not data, neither of which was a good sign, but I eventually found that it does exist.

Among the components of the Gamekit package, designed to help developers making networked games, is Peer-to-peer technology, which allows for communication of data over Bluetooth or WiFi. Some quick examination of the documentation looks promising; it says that although it was geared towards games, it can be used independently in any kind of application, and that the data being sent is defined by the user, which is very good news.

It appears that the implementation will involve making and displaying a peer picker controller, which in turn will create a session object. This session object will be configured in a bunch of ways (just looked at it all quickly to try to get an idea of how it works), and will be the point at which all data passes through. The data transfers will cause the session to call delegate methods, which I think will be implemented in the peer picker controller. The peer picker controller will also be where the user will be able to choose from other sessions to connect to for the group recommendation.

As far as some of the other considerations we discussed, a few seem pretty covered by the API. The unique peerID is built into the session object, and a display name may be set. I imagine that the implementation will have the Group Recommendation button pop-up some kind of prompt for a display name and then move into the peer picker controller view, or the display name will be set on application start and the button will just move straight into the peer picker and init the session with the display name automatically. Also, there are methods available for sending to all connected sessions as well as to a specific one (according to peerID).

Much less fortunate is the plan to have the iOS versions work with the Android versions. Because the Bluetooth capability works via the Gamekit package, it already seems highly unlikely that its methods to find peers would register the Android version of the app, much less actually connect to the Android version of its ‘session’. Looking it up to see what others have found, it seems to be true, with some having slightly more detailed explanations noting that Gamekit will only work with iOS devices or MFi compatible devices (meaning Made for iPhone/iPad). Which doesn’t include Android, apparently.

To sum up, I think that I can start working on some tests to get Bluetooth capability into the iPhone/iPad applications and eventually to the actual Group Recommendation work, but that cross-device compatibility might be outside of the API. I’m not sure if we could actually finish the Group Recommendation functionality right now, however, since the Make a Recommendation function does not work for me yet, and apparently still uses the server anyhow when working for demos, and because the Preferences is also not complete yet. All three could end up in some sort of pseudo-finished state though. I really wish I knew how to get the search/recommendation functions to work on my end, especially recommendations when I reach the point where I want to send recommendation data across the Bluetooth connection. For that matter, it seems we will only be able to test the Bluetooth capability when the group gets together at the lab, because the Bluetooth capability will apparently not work on the simulator, only a device.

Today I worked entirely on the Recommendation Restrictions part of the Preferences UI. I started out by adding modes to the recommendation view to allow changes of the navbar buttons and title and for any later changes that would require differences between using the class for making a recommendation and when using it for recommendation restrictions (in the Recommend tab and User tab respectively).

When working on the navbar buttons, I realized that in order to stay consistent with the other views in the app I should probably make this a modal view instead of the current pushed view, and add the Cancel/Done buttons to it instead of the current default left navigation button and right Commit button. To do this, I needed to build the modal view in the same way as previous changes by first making the new navigation controller for it (so it has a navbar) with the view as root, and then presenting it modally. I added the buttons to the view as calls to the navigation controller, which calls functions in the view which in turn call the delegate’s processing functions to both dismiss the modal view and get the data to where it needs to go. In this case, that meant making and specifying the delegate for the MakeRecommendationViewController as the UserPreferenceManagerViewController.

Once I got the delegate stuff working correctly I was able to give the Cancel button its functionality. At this time, I also realized that the change to a modal view also broke the buttons that would bring up the description generators for each of the Dish and Wine descriptions. This was due to the way it was calling it up, where it previously presented the modal view on the application’s current tab controller. However, since it was now in a state where the modal view was being shown from a different navigation controller, this call needed to change. Using the modes I made before, I added a new set of rules so that the right calls for the modal presentation and dismissal were used.

After this, I could finally begin working on the Done button’s functionality so that it would return correctly and update the main view. At the time, I just had it so the Done button would dismiss the view but didn’t actually do anything. After considering a few ways to return the data, I tried to go for the simple solution by creating a NSMutableArray and inserting the two NSArrays that hold the NSArrays of Pairs that return from the description generator. I again had the various layers of this object outlined on paper because it was so convoluted and frustrated several attempts to call certain sections of it.

Returning this NSMutableArray to the delegate, which is the UserPreferenceManagerViewController outside of the current controller which is dismissed on return, seemed to make sense. It would be added to the main view’s NSMutableArray of restrictions, making the final chunk of data a NSMutableArray of NSMutableArrays of NSArrays of NSArrays of Pairs. However, when I implemented it this way it failed despite several stabs at different ways to return it, thinking it was my method of return.

After a few failures, I went back and tried simplifying the data being returned to see at which layer the return would start working. As it turns out, I found that the data would write fine to the NSMutableArray once I hit the NSArray layers. Confused, I went to the ever useful documentation to try to figure this out. Basically, the fact that NSMutableArrays used the addObject function to add data was no lie, it literally will only add objects with NSObject as a superclass…which does not include NSMutableArray itself.

I knew, then, that I had to use a different container, and the obvious choice was NSArray. Looking at the NSArray documentation, it was simple enough to change it to save the two NSArrays of NSArrays of Pairs into a NSArray instead of a NSMutableArray, and this NSArray could be stored successfully in the NSMutableArray. Now that’s a lot of arrays.

At this point, the Done button was now successfully writing the data to the array holding the recommendation restrictions, but the display was still showing my dummy test cell. I now needed to work on rendering the data in its corresponding cell.

I thought a while on how to do this, because it isn’t a view seen anywhere else in the application yet. What needed to be displayed was both the Dish and Wine descriptions; it needed to show the entire recommendation restriction in a single cell. I decided to go forward by changing the UITableViewCellRecommendation to add a new initialization that would work with the new data format as the input. I expected this to need a mode to be made to keep track of what the cell was being used for, a new init function, and some new logic in the various functions related to cell generation and height calculation in both the cell and view classes.

My initial attempts crashed, and a series of tests using different numbers of set rows to check my logic for distinguishing between the dish and wine description pair counts revealed a few issues that needed to be fixed, similar to the ones I encountered when doing the logic between the necessities/exclusions before.

The result showed all of the data, but as you can see in the screenshot needed a space in between the two descriptions to make it clear where the two descriptions are and still needed all the height changes.

I made the space by creating a dummy cell in between the two, updating the logic once again to account for the extra cell in between. This brought up some more issues with displaying it, the most prominent being the apparent loss of the bottom pair for the wine description. After a whole bunch of tests on the completely wrong things, I eventually suspected that it might not be the logic or cell counts that were off, but the height settings. Extending the height manually confirmed this, and it was simple to simply fiddle with the height calculation functions to add the needed space to account for the dummy spot.

With that, all the buttons in the Preferences UI function and return the data correctly, which is displayed fine in the main view. There are just two major issues remaining. The first is that the preferences are not editable once entered, and I need to change that so that they will be selectable and will call up their respective views with the existing data so the user can change it accordingly and will update the view correctly on return. The second is that the preferences data is still not persistent; when the user exists out of the Preferences UI all the data is lost…clearly not something we want from a user preferences function! As far as the UI itself, however, it is pretty complete.

So I had hoped to finish implementing all of the functionality for each of the buttons and get all the data to return correctly to the main view. As it turns out, I was able to do this for all of the Food/Wine Restrictions, but did not have time to begin work on returning the data from the Recommendation Restrictions, nor fixing the UI for the views being called (will talk more on that later).

The first thing that I did was to simply connect each of the buttons to their respective selection windows. To reiterate, each of the Food/Wine buttons call up the description generation view where a list of properties is made, whereas the Recommendation button calls up a recommendation view where the same process is done, but on both a dish and a wine before returning back to this main view.

After some fiddling I got them all to return without crashing, although the content being returned was not implemented yet. The initial problem with the crashing was due to me dismissing the new views incorrectly, which was easily fixed. At this time I also realized that there are several things I need to fix with the Recommendation restriction UI, such as changing the title and removing the commit button since it’ll return using the back tab instead of that. I’ll get into more detail on plans for this section at the end, since I did not work much on it today.

I worked slowly on figuring out how the data is being passed around and in what form in various other functions to try to grasp how to do it here. In particular, I looked through the MakeRecommendationViewController and DescriptionGenerator classes.

I began by simply adding test buttons each time, just to make sure that I was indeed adding data and returning correctly. I ran into some crashes before I started adding the cells since it was calling the cell at indexPath but I had no code there to return a cell. During this change I realized that I needed some sort of modes to distinguish where to add it, due to the way I needed to handle the indexPath as a combination of both the necessity and exclusion counts. I did this by adding an enumeration to the class for easy reading and the addition of the mode variable.

After adding the modes to make sure I was accessing the right data at the right places to prevent crashes, I was able to make the test cells. I also noted at this point that although I was setting them to be read-only right now and therefore unselectable, I would need to make them selectable so that the user could change their previously set preferences. I don’t want to work on this until I complete the entire basic functionality, however, so I will just keep this in mind.

Another issue is how you can see that at this point all the rows had that green + next to it, which I only wanted for the actual Add buttons. My initial attempt to change this by changing the cell initialization call did not work, so I went to the documentation. After looking through this, I tried to change the imageView thinking that it was an image being set somewhere, but trying to remove it that way did nothing. I eventually realized after looking around some more that it was not an image but the UITableViewCellEditingStyle. This green + is due to the style being set to insert, whereas I wanted none. Once I figured this out, it was simple to fix by putting in a switch statement with some logic governing where to use each style.

I continued to trying to display the actual data. My initial attempts failed despite me trying several kinds of formats for the data I thought was being returned. After going back and reexamining how the data was being passed and my calls to try to get the data into the cell I realized that I had actually gotten the correct format the first time, but had simply messed up the call.

It was saving the data as a NSArray of a Pair like I thought, but I was accessing it by calling the entire data NSArray in the main view, where I needed to call the index instead, which would get the correct NSArray. In other words, in the case of _foodNecessities, it is a NSArray of NSArrays of Pairs, and I was calling the first index right, but did not go the extra layer that I needed to access the right piece of data.

Just a reminder that all this work was aimed at the Food/Wine restrictions, not the Recommendation one, which will work differently and will have a completely different data format and different rendering in the UI.

After getting the data to display correctly, I realized that it was not resizing the cell correctly, simply showing it as the default height. I also realized that there were issues because I forgot that I needed additional calculations within my logic when figuring out which index of the exclusion to access for that, since the indexPath would count both the necessity count and the exclusion count since it is the index for the entire section. After a bit of testing, fiddling, and retesting, this was fixed with little trouble.

I fixed the size by implementing the height calculation function, which was previously left to the default, and adding a switch statement with the usual logic to call the correct height function for each cell.

This should finish the UI part of the Food/Wine restrictions, apart from needing to change the cells from read-only to editable in a way that will call the description generator with the correct data and edit the cell on return. This will have to wait until I finish getting the UI to work for the Recommendation restriction, however, which I hope to finish tomorrow…technically today now.

For the Recommendation UI, I will need to change it so that it doesn’t have the commit button, since it just needs to return the data via the left button returning it to the main view. Following this, of course, is the need to get the view to return the data upon this return, and the big task of figuring out a way to display this data. Since it will likely be the large recommendation data being returned with both the dish and wine data, it might need me to define a new cell type. I’ll have to look into this more when I actually begin work on it tomorrow. I also need to change the title, since it is not being called as the Make a Recommendation function, but rather just to get the recommendation format and return the data to the view, the identical reason why the Commit button is unneeded.

Today I began work on the actual UI for the preferences. After spending some time looking at the code and fiddling with how the sections and cells were being defined, it was pretty simple to get the buttons looking how I imagined, seen above in the screenshot. The only issues were in figuring out how to calculate the rows/sections correctly between the two divisions in the first two sections, which just required created separate data arrays and fixing the logic to account for the rows being in the same section.

I also looked over the plans for what each button will lead to, and realized that I had actually overcomplicated my idea of how the food/wine restrictions will work. I had said that I would add a new line to the description generator to show that it is a necessity/exclusion, but when I looked at that idea today I realized that it didn’t really make that much sense. The button should lead to a description form for the dish/wine being described, but that description shouldn’t really have the preferences type in it. When I was doing the new UI I realized that in order to keep track of the rows/cells I needed to separate the data for each of the necessity/exclusion groupings for each section, and in the same way it should be easy to simply copy the description upon return into the correct array.

I am still unsure as to what, if anything, I need to do to these arrays themselves. Do they automatically persist somehow, for when we need to make them affect the search functions, or do I have to link them somehow myself? As I noted last time, this is an issue that I will not be worrying about until I finish the entire UI. Once I get the entire UI working so the various descriptions return and display correctly, then I’ll worry about where/how all the displayed data will be saved or whatever they’re supposed to.

Tomorrow I hope to finish the second layer of the UI, which will be the description views for the Food/Wine Restrictions and the dual-layer view for the Recommendation Restrictions. Ideally, I will also be able to get them all to return correctly as well and display on this parent view. Once that is done, I’ll debug and test that on Sunday and when I get a response about the data storage/persistence question I will work on that too. Realistically, I expect Sunday to mostly be debugging getting the data to return and display, but you never know.

The final planned section of my work for the upcoming release was to implement the Preferences UI (and hopefully some functionality). Unfortunately, this needs to be done by Monday when we freeze new features and focus on testing/debugging, and I am already starting late due to needing clarifications on what we actually wanted the UI to have and what the functionality would eventually be. This was the first time that I really wished I was in our lab at Winslow because this area is completely new and the existing UI (just a dummy front page right now) is pretty much being completely changed and extended, so I spent a while working out how everything would flow and look like on paper, which would have been a great time to actually use our whiteboards in our room. All the screenshots in this post are of some existing stuff to try to help show what the planned UI will be based off of.

The Preferences UI will be located under the Food/Wine Preferences section in the User tab. Currently, it only consists of the above dummy page with no functions (although the first button will still crash the app, due to what looks like a partial start at implementing something).

As I mentioned, I was unsure of how exactly was expected of each of these in terms of function, as well as how they tied in with the existing recommendation system, which I also had problems in even using so I could not look at it to compare or infer anything. After e-mailing Evan I put together some ideas and sketches of how I think will end up being the UI, though I have doubts that I will be able to get the functionality working in the next three days, especially since its closest model, the Recommendation UI, is itself incomplete.

Instead of what you see here, with the three Necessity/Exclusion/Pairing options, it will have the same type of layout, but with different top categories. I wish I could put up a graphic here, but my sketches are kind of…messy, plus I don’t actually have a scanner. There will be one for Food Restrictions, such as “I will only/never eat ___”, one for Wine Restrictions, such as “I will only/never drink ___”, and one for Recommendation Restrictions, such as “If I eat X, I will drink Y”. Under each of the Food/Wine Restrictions will be two buttons for the Necessity and Exclusion types of restriction, and under the Recommendation Restrictions will be a single button.

The Necessity and Exclusion buttons will lead to a Description Generator interface similar to that from the Find functions of the Recommend tab, shown above. However, instead of starting out with the read-only Is A for the category of item being searched for, it will have the Is A for Food/Wine as well as a new preference type that will be specified as Necessity or Exclusion. I’m not yet sure how hard this will be to do, but I know it’ll depend on how the current class handles the read-only of that first spot. If it is simply hardcoded to do special stuff to index 0, then it might need a lot of added conditionals and fiddling, but if it is part of the initialization or special functions somehow it might be easier.

The Recommendation Restrictions button will go to a different kind of interface, similar to the dual interface seen in the Make a Recommendation function in the Recommendation tab, seen above. Each of the buttons will go to a description page similar to the Necessity/Exclusion ones, but this dual section is needed in between for the paired nature of the restriction.

The biggest problem if I get far enough to worry about the actual functionality of this is that I haven’t worked with and so don’t have a clue as to how the actual data needs to be stored. Will these preferences be saved in some sort of persistent preferences data for the user, or will it somehow integrate with the recommendation info? Either way, I have no clue how it will work, especially since I have not been able to successfully add or view any recommendations! After asking Evan about this, I found that the make might have been affected by a server change done by him for a demo, and the view function isn’t actually implemented yet.

What I plan to do is to get the entire interface working so that all of the various views discussed above can be reached, but I will not worry about whether the interface can actually do anything functional until I finish the UI itself. In fact, it wasn’t really clear if I was supposed to add the functionality as well, but the UI is definitely something that I will try to finish so people can at least get an idea of how it will work, even if it doesn’t yet.

Oops, this is actually later than I had wanted to post this, but I was so happy to finally get everything working (as far as I can tell) up to this point that I completely forgot to write the post. I spent the last two days working on rotation, but really most of the time was spent jumping between rotation and the huge legions of different kinds of bugs I found when testing. Because the rotation change required so much testing on both the iPad and the iPhone simulator, all of those bugs that I had missed previously all jumped out, and fixing some led to others which led to massive disorganization as I tried to fix them all at once.

I started off by fixing an issue I had noticed while writing the previous post, which was that there were issues with the rotation when going 180 degrees rather than the usual 90, due to the way I had implemented the checks. This was an issue that affected all instances of that multi-cell table, and that table is rapidly becoming more frustrating as the project goes on since so many things go wrong with it. This particular issue was easy to fix however, and I just improved the logic governing the rotation check. I did this fix first in case I needed to use that same logic again later, since it will apply in most, if not all, cases where this table appears.

After that, I went back to implementing the rotation to the various parts under the Recommend tab. I once again encountered the resizing issue with the property view controller due to its use of hardcoded sizing. I decided to try a different method of fixing it this time that I had thought of after the last fix of this kind. Last time, I had created a single call that would fix the views, but did all of the actual logic and size decisions within that function in the target view. This time, I tried to do it differently by deciding the frame sizes outside of the target and putting that into the actual call, so that the function itself would stay the same and the argument would change instead of the other way around. I wasn’t sure which would end up being more readable/maintainable or if one would be easier to implement, but figured if this way was better/worse then I could go from there after trying both. It did work, though it still required a lot of fiddling, but in terms of readability and ease of implementation I still didn’t really notice that much of a difference. Depending on what the fix is, both of these differ and work better on one or the other depending on the circumstances.

Continuing from here, I moved on to applying the rotation to the modal picker. I expected to run into yet more problems considering the issues I had in first implementing the modal view, but was happily surprised when it went smoothly. Adding rotation to the other options available in the Recommend tab also went smoothly after these changes.

I had started on further fixes when I realized that I had actually forgotten to test these fixes on iPhone. This turned out to be a good thing that I remembered before making more changes, but also revealed a ridiculous amounts of issues. The first and most annoying was the same issue where everything would load fine in the current orientation but would freak out when rotated due to the frame width somehow being loaded either at an odd time or some other reason causing it to flip orientations where it would load as if it was in the other, without any clear reason or easy fix.

Working on it, I first suspected it was due to the picker frame, but long and frustrating testing with different combinations, methods, and times seemed to indicate at last that it was perhaps due to the appearance animation itself causing the odd flipping of the orientation at a time that none of my changes were affecting. After doing another series of attempts and tests I managed to apply a fix to the display animation so it works fine. After this I went back to the iPad to test that I didn’t somehow break something on it. Thankfully, no.

When working through the previous issue, I had found another one and realized that an older fix for the iPad had accidentally affected the iPhone where my modal view changes had replaced the pushed view on the iPhone, which broke the functions since the associated changes were properly filtered between iPad/iPhone. This was a simple fix, just needed to add the conditionals I had forgotten.

From here I went back to an older problem that I had noticed with the multi-cell table. When going from a view containing a multi-cell table, if the orientation was changed in the top view the multi-cell table would load in the opposite orientation upon return. Testing made me suspect it was once again an issue with somehow initiating the wrong function upon return from the modal controller, but was not sure of why or where. I tried to fix it by implementing a ‘return’ function so it worked the way I wanted. Reading the documentation, I figured out that I needed to implement the needed fix in the viewWillAppear or viewDidAppear functions, which were not currently implemented as the view simply used the defaults. Finally, doing this succeeded in fixing the error.

With that, all of the previously noted issues were resolved so I started a new complete check of all the features I could access on both iPhone and iPad. Although the debugging will have its own phase later, I really wanted to get them to a stable state before moving on to the final set of goals in implementing the Preferences UI in the User tab, which I am still unsure of the specs for and so am uncertain as to the time it’ll eat up.

One odd thing I noticed was that the iPad seems to only display one item in the Twitter Post view above the input, whereas the iPhone showed the two buttons that I spent so long making sure worked. Looking into this, I found that it resulted from the fact that the code dynamically decides which buttons to display, and the logic governing whether it shows one in a normal view or more with the multi-cell view is for some reason performing differently on the iPad. Plus, the buttons regardless of whether there are one or two…don’t function. Thus, I am deferring this issue since it seems to be an oddity of the internal reasoner which isn’t really something I should be fiddling with and because it displays fine either way and with no functionality the buttons don’t actually matter as of yet.

Another issue I only noticed after going back and forth between the iPad and iPhone views was that in the Add Property views, the display wasn’t actually clearing old values when adding a value in another slot. The results would be correct, but it was as if the screen was not refreshing after a selection, only refreshing the one spot on the screen. After some more testing it was fixed by adding a reloading of the view upon return, which also fixed a few other aesthetic issues with things not being deselected and such that I hadn’t noticed. Oddly enough, this issue never affected the iPhone view, and I suspect that this is due to differences between how the modal and pushed views return and how the view underneath handles the top view being dismissed. I could never find a definite point at which the two diverged in this despite looking over all of the associated code again, however.

With these fixes, it seems that both the iPhone and iPad versions of the Mobile Wine Agent are stable in terms of retaining the same functionality they had when I explored it at the start as well as the aesthetics looking the way I wanted them to after the previous changes. The next part is the work on the Preferences UI, which will be rather confusing as I’m not really sure of the specs right now. I had been told it’d be similar to the Recommendations, but the Recommendation functions are largely inaccessible or nonfunctional, at least in my testing, and I am not sure what that entails. Since I could not successfully add or view any recommendations, and the preferences is supposed to function by next Monday, I am kind of confused. I’m waiting on some more clarification from Evan before I start on the next part, which means more delays as well. We shall see how that goes.

Haven’t updated in a bit because I was hoping to finish the rotation implementation quickly and just have the one post, but no such luck.

As I always do when starting a new change I began by looking at what I would need to change and figuring out which files are involved. In this case, that meant backtracking through the views to locate where the entire app was being started from to find the top navigation controller so I could work down from that in implementing the rotation section by section.

My first attempt was to just get the rotation working on the restaurant top view, but it didn’t seem to be working at first. The reason turned out to be due to the tab bar controller which has each section’s navigation controller held in itself. This tab bar controller does not allow the sections to rotate unless every single one of the top controllers for each section has rotation allowed for that orientation. After doing so, I began the work on each section, trying to focus on one at a time.

I started with the restaurant view first, since it was the first one I worked on for the project (with the social UI) and I knew that it would have issues with that same section due to the way the multi-cell view works. When I had first worked on it, I had noticed that the sizing was almost entirely hardcoded and that there were major issues with trying to use the frame width or height to do things, and it definitely showed up worse than ever when trying to get it to rotate correctly.

After a bunch of trial and error fixes to figure out how to get it to look best in a landscape orientation, I tested it out and realized that although it would load fine in the current orientation on the initial view (going from the map to the restaurant info view) it would not adjust at all when rotated, despite the rest obeying the autorotation.

I tested with this for quite a while on both iPhone and iPad (since I needed to implement rotation on both) and found several issues, some of which seem contradictory. One of the major reasons why the sizing was going so horribly wrong on rotation was because any calls to the frame were returning very odd results. On iPad, it would sometimes return the value for the opposite orientation or with iPhone dimensions, and on iPhone it would still have orientation issues. I realized at the end that I might be able to resolve this with some work on incorporating frame changes in the rotation, but did not end up fixing it like that at the time (though I may come back to this when we debug, to try to make the code cleaner). I thought at first that this was an issue with the frame itself, but since it loaded fine with the same code on initial load, this seemed contradictory. I suspect it is due to resizing a view at a time when the frame hasn’t updated yet or due to the way the subviews were added.

Either way, I ended up solving this at the time by writing a new ‘reset’ function for the embedded subviews which corrects for this problem upon rotation by redrawing the subviews with the correct sizes on rotation on both iPhone and iPad. This was again after a huge amount of testing with calling the function at different times and trying to figure out why contradictory results were happening. For example, the check for orientation is the opposite on initial view and in this new function, which makes…very little sense, but would not work any other way. Again, I suspect this is due to when the function is being called, but playing with the call time did not reveal anything particularly helpful.

Strangely, implementing this function fixed the iPad but broke the iPhone view again, and required some more fiddling with how the initial view and on rotation view updates were working. What I ended up with seems to work but isn’t as clean as I would like since much of it is hardcoded adjustments with the frame largely ignored, and I hope to look at this again during the debugging phase if more pressing issues don’t appear.

With that the Restaurant tab appeared to have all implemented views rotate correctly except for the Facebook/Twitter buttons. The Facebook button gives a warning that it isn’t implemented yet, but the Twitter one could not be accessed without being logged in. I decided to go and make sure that the Social tab had all of its rotation implemented before coming back to work on this, since that tab contained the actual Twitter login function.

The Social tab was much simpler to fix, requiring pretty simple changes and no ridiculous complicated issues like the social UI in the Restaurant tab keeps on giving me. This was made even more obvious when I came back to the Restaurant tab after making a test Twitter and linking it to the app.

Once I was able to see the Twitter UI itself, I realized that we hadn’t realized that it needed its own changes for iPad use before I even looked at rotation. In particular, the input box for the user’s post needed to be resized for iPad and the colors needed to be altered to fit in with the different styles on iPad.

After fixing the Twitter UI up and implementing the rotation, I once again found an issue with the table above the user’s post input which, not to my surprise, turned out to be using the same multi-cell table view that has been beating on my head since the start of the project. I once again spent a few hours trying all sorts of changes and tests to try to both get this to work and to keep the other multi-cell tables from going berserk, since there were new issues on this that the other didn’t. It had many of the same issues, but also many new ones because this view had two buttons instead of three, causing me to need even more specific adjustments according to both the number of buttons and which orientation it was in.

Even when they would both resize and rotate and appear properly for both instances of the multi-cell view, there were new issues going back and forth between the two views that held them (going between the restaurant info view and clicking the Twitter button to go to the Twitter UI and back) because it would seem to reset the orientation and not trigger my reset function so they would reload in the opposite orientation again.

Yet more testing indicated that it seemed to trigger the new function I had made on the return navigation, instead of the initial load one, which caused issues due to the earlier observation that they used different filters for the odd behavior displayed on rotation…which didn’t apply in this case. I fixed this by fixing how the code determined when to reload the buttons to only apply when going from an orientation to another one. As I write this I realize that I should go back and test whether the iPad goes 180 degrees via two rotations or one, since odd behavior will probably result if it does so in one. Note to self!

After doing that I had looked at the User tab, which didn’t require many changes since most of it is not implemented yet. I’ll have to come back to this when I work on the preferences UI, however.

Still left is the big Recommend tab and all of the bits of the description UI that need to have rotation implemented. Also, as I mentioned a bunch I hope to go back to the multi-cell issues and make sure that it is all working in all cases and clean up the code even if not. The plan is to finish up the Recommend tab tonight and tomorrow and spend Tuesday checking for any other issues that I missed in my initial war with the multi-cell tables (and other sections…but mostly that one).

The last few days were spent just finishing up the description UI as I did the final changes to fix the property values being displayed and moved the UI from the fullscreen tables to a modal window view. Although I had worried about finishing this section on time, it ended up working out (relatively) smoothly near the end.

One of the lingering issues throughout this change, which I had deferred until now, was that some of the values being displayed weren’t matching up to those appearing when using the old wheel pickers. In particular, the Property values were much different and I had thought that the Has Color was also showing too many choices. When looking into the Has Color values, I realized that it wasn’t actually wrong, but the issue was arising from the fact that there were actually two Has Color properties, one with the three wine colors and the other with a wide range of colors. This meant that there was only the one issue with the Property values.

I tried a whole variety of different calls to try to replicate the call, but had no success. After talking with Evan, I realized that the problem was not in what my method, but a simple misunderstanding I had on how the calls to OWLClass worked. One of the methods that I tried several times in several different ways was setting the values using a call to OWLClass for all properties with the domain being a certain class or URI, but I was unable to get any meaningful results. This was because I was not using the correct URI and trying to retrieve the Wine class as the domain by searching for @”Wine”, even trying some superclasses like @”EdibleThing”, etc. As it turns out, I needed the full URI for it to work (@””) which in hindsight makes perfect sense considering that’s how the queries in previous projects worked. It was a pretty simple fix in the end, but it took a long while since I didn’t realize my oversight.

After fixing this, which brought both Has Color properties into the list of selectable Properties, I discovered several minor issues with how the selection window was working because of the newly made distinction between single/multi tables.

One issue was where for one of the Has Color’s it would work fine, but for the other there was an issue where editing a singly selected value would start it with a checkmark for the current selection and would not automatically reset if another was selected (the screenshot explains it far better than me). This was fixed quickly since it just needed some tweaking of how I implemented the single selection versus the multiple selection tables.

Another issue was also revealed by the two Has Color’s, where one wouldn’t actually display the selected value (though it would work correctly if Done was hit after selection!). This was because the two Has Color’s actually differ in what kind of property they are, which led to different behaviors between them that weren’t covered by the code displaying the selected value when added. Internally there is actually a selectedValues and selectedValue and so it was a simple fix to make sure the correct one was being written to and read.

The ultimate goal of the description UI was to move from the wheel picker to a modal window one. A modal window would be the ideal choice because it looks better than the picker wheel but also does not need to move to an entirely new screen the way the normal selection table does. Since I had been worried about time and was not sure about the implementation for the modal window, I had moved first to that normal selection table, which simply pushed the entire view on top of the navigation stack, planning to extend/change that to the full modal table if I had time. This way, even if I did not have time, I would still have a working implementation, just not the windowed view.

Unfortunately, when I first started this plan, I really had no idea what a modal window was. Based off of the example (see the screenshot), which was just a modal window seen in the iPad settings, I first just tried to change the size of the view itself, thinking that I could just shrink and move the view as I wanted. However, I eventually figured out that the navigation controller itself will ignore those changes and resize the window to fit its navbar and screen when the view is pushed onto its stack.

After looking through some other controllers, I tried to use a popover window to perform the action, which is a window that can be made to popup at a given location or from a given button. The main reason I tried it was because I thought that it would be helpful to have the property that popovers have where you can dismiss them just by clicking outside of it; to enable faster selections if people change their mind and because it sounded similar to the example I was looking at, with a window popping up with the view. However, after setting everything up to try this, I got various results like the screenshot, but it wasn’t really what the example looked like.

Eventually, I found the documentation on how to make a modal view and began implementing this. Directly presenting the view modally resulted in almost exactly what I wanted…except that it had no navbar so all the user could do was scroll around since it couldn’t be dismissed or a selection made. Still, I was pretty happy at this point since I had finally gotten it to at least look the same as the example (mostly).

Thanks to all my previous issues with the navigation controller, I had an idea of why this was happening now. Because the navigation controller basically keeps each screen on its stack, all of the other work was using the same navbar and could just push/pop the views and the bar would update fine. However, by presenting this modal controller, it would not be part of the old navigation controller, and would need its own. To add the navbar I had to first make a navigation controller, initializing it to have the selection window as its root view, and then I needed to have the current view with the old controller present the entire thing as a modal window:

UINavigationController *temp = [[UINavigationController alloc] initWithRootViewController:_assistant];
temp.modalPresentationStyle = UIModalPresentationFormSheet;
[self presentModalViewController:temp animated:YES];

Doing this got what you see in the screenshot. This looks pretty good, except that it still doesn’t have the button to go back and save the selection!

This change took longer than expected. The reason there was no back button was again due to the way the navigation controller works. Since the navigation controller in the modal window is actually separate from the old one and has just that selection table as its root view, there isn’t a ‘back’ to go to (the back button is actually generated automatically, which is why nothing is displayed here on the left).

To replicate the same results as the old view on the old navbar, I needed to set a delegate for the assistant pointing back to the main view with its navcontrol. Once that was working, I could make a Done button for the left side that when clicked would call the delegate’s didDismissModalView function. I had to implement this function as well, which just saved the assistant data, cleaned up afterwards, and closed the modal view.

After this I just fiddled with the single/multi selections, eventually deciding to use the modal view for all of them because it would be consistent and I also like this modal view a lot more than the old one, for all the same reasons I liked the wheel in terms of speed/what is still visible.

Here’s a screenshot at the end with everything finally working:

All in all, this last shift from the pushed view to the modal view was another one of those really enlightening issues, which helped me understand the navigation controller and how views are actually handled, as well as how delegates work.

The next few posts will be on the next task, which is implementing all of the rotation and getting all the views to not explode when it does so.

Before I continued on to getting rid of the rest of the wheel pickers, another issue that I had to address was how the selections were appearing and being implemented. Because I made the single selection table using a simple/fast change in the code that was specific to the specific case of the Property change I was testing, it ended up with a few issues with how it looked and with being unable to be extended to the other changes. Again, sorry about the lack of screenshots, I either forgot or didn’t think the change warranted one.

First, although I had it so that only a single selection was allowed and displayed, it would only work for the first selection due to me using a null property as the filter, which is far too specific. I went back and made it so that the assistant code determining whether or not multiple selections are allowed are based off of a new variable, single, and added a constructor that can set this (it defaults to false/multiple selection). This is so that all of the existing code and calls to it are unaffected. I followed this by making a new function for the picker code to create a single selection table, which created the assistant using this new constructor. Before, I was only relying on the single condition in the assistant but by extending it out this way I can now reliably call the different tables for any of the picker views and with a much clearer method of doing so.

Second, because I had initially just done the simplest change possible to get the function I needed, the graphical animation itself was skewed; it had a very short highlight animation that did not stay, due to me refreshing the data when guarding against multiple selections. To solve this, I first tried to get around this by rehighlighting the correct row after this refresh, but that didn’t work. After doing the first part while thinking on this issue (I had actually started this one first but moved on since I was stuck) I realized that since the single/multi creation was more distinct, that I could actually just stop with the checkmarks altogether since there is only a single selection anyhow, and retain the correct highlighting since the refresh was only needed to fix the checkmarks.

Once again, I’m baffled as to why different values are displayed between iPhone/iPad. I had noted this in an earlier post, because I was trying to translate the Property picker and couldn’t replicate the call. This is even stranger though, because I didn’t change the way the other pickers pulled the valid values at all, yet they still perform differently. For example, Has Color is pulling a whole range of colors out, whereas the iPhone pulls just the Red/Rose/White you would expect. This needs to be fixed, but since nothing should have even changed to affect that, I’m at a loss as to what I need to even look at.

Other than that, however, it looks like all of the needed functionality is complete and all of the wheel pickers have been replaced by the table ones. The next day or two will be spent looking at the appearance, now that the functionality is fine, to try to make sure it matches how we wanted it to look.

While traveling with my family for New Year’s I spent most of the car ride trying to think about the issues I was having with this, especially since the deadline for finishing the description UI changes is getting so close. I hadn’t really thought of anything, but did realize that I had been staring at it so hard that my attempts at solutions were getting unnecessarily complicated and that I should probably take another look at it after the break of New Year’s.

As it turns out, once I came back and reverted most of my changes the problem seemed much more obvious; clearly looking at it after getting away from it for a bit helped to get me out of the block I was having and so I took a much different approach afterwards. After a few tests that I thought of while on the trip I realized that some of my changes were not working because, quite simply, they were not even being reached. I had been doing some of the changes assuming that I was editing the right spots but after doing some debugging I cleared this up finally and was able to get the Property selection finished. I didn’t really take that many screenshots for this section since it was mostly just restoring the functionality that it had before, but fixed to work with the new format and also because the nature of the change now has the connected parts on different ‘pages’ so it’s harder to screenshot.

Similar to my mobile UI work, once I had my sort-of-epiphany about how everything was working together it fell together fairly easily. The setting of the property is now working so the function is working completely now. I just had to resolve some minor issues with how the addition of more selection tables affected how the others were clearing/loading their own values since they used a value loading system that only worked because there was only one thing using it. I also noticed that the values are prone to odd resizing of the window if a large number are chosen for fields allowing multiple values, which I will try to look at after the wheel changes.

In contrast to my last post, I am now pretty sure I’ll get all the changes completed now that I finally have a grasp on how it is all working and how to do the changes I want. I’ll be working on phasing out/converting the rest of the wheel pickers tonight and tomorrow, leaving the last two days for more subtle changes and a fix for that many-values issue. Hopefully the next part (implementing rotation) will be easier since I’ve been thinking on how that’ll work since the beginning of the project, but I’m pretty sure Murphy’s Law will intervene.