My Cocoa Bits

2014.08.07

UIScrollView not scrolling (!?)

Filed under: Uncategorized — rtovars @ 16.48

Two problems and two solutions in a row today… I really should be reading Matt Neuburg’s books iOS 7 Programming Fundamentals: Objective-C, Xcode, and Cocoa Basics and Programming iOS 7 to avoid such rookie mistakes!

Anyway, I was trying to work with some UIImageViews embedded in a UIScrollView to show some sample screenshots, and in spite of me setting up “correctly” the UIScrollView‘s properties, the images were not responding to the horizontal swipe gestures as I wanted.

UIScrollView not scrolling

UIImageViews embedded into a UIScrollView

I found this answer to my problem in StackOverflow and I was about to implement it, when the word “scroll” called my attention and I immediately went back to Xcode and saw this:

UIScrollView proper settings

Correct settings for a UIScrollView to scroll/paginate

The problem was that initially I unchecked the Scrolling Enabled setting, as somehow I naively assumed that since I only wanted to paginate through the images I didn’t really need to scroll through them, as this meant (to me) that the images would slowly move and maybe not exactly fit a “virtual” page frame.

To my surprise, when I checked the Scrolling Enabled option and ran my app on the Simulator, I was able to smoothly scroll AND move page by page through the different views.

Now repeat with me at least 10 times: “Paging through a UIScrollView necessarily requires the Scrolling Enabled option!”.

I hope this time I won’t forget it and that this post will help you in case you too make this rookie mistake.

Happy Xcoding!

UISplitViewController, delegates, iPad screen rotation, and UIPopoverController

Filed under: Graphics,Storyboards,Xcode — rtovars @ 11.14

OK, yesterday I had a problem with a UISplitViewController. As it’s customary, I wanted my app to work in both Portrait and Landscape. My initial implementation was working fine when in Landscape mode, as both Master and Detail views were being shown on the screen. However, when I rotated the app on the Simulator to Portrait mode, and the Master view disappeared, I was not able to see the button on the navigation bar that should have called the Master popover (UIPopoverController) to appear to the left, nor I could swipe to the right to make it appear.

UISplitViewController with no popover button

Initial implementation of the UISplitViewController lacking the popover button to call the Master view.

I struggled for a ridiculous amount of time, checking my code, verifying the outlet connections and comparing those to another project where I was able to successfully implement this functionality, but I couldn’t find anything strange.

However, after leaving for the day and upon arriving to the office today, I took a closer look at my previous working implementation of this feature, and I found out that the problem was that although I had double and triple-checked the outlets and delegates in Interface Builder, I had forgotten to set the UISplitViewController‘s delegate on code within the viewDidLoad method in my Detail view. So, after adding the following line everything worked fine:

self.splitViewController.delegate = self;

Now I’m able to see the Master popover (UIPopoverController) when on Portrait mode when I tap on the appropriate button on the navigation bar, or when I swipe to the right.

Once more, the lesson learned is to verify that outlets and delegates are set up either on Interface Builder or programatically.

En fin, keep this in mind and keep coding!

2014.05.07

Horizontally center a view (image) within a UIScrollView using Auto Layout

Filed under: Graphics,iOS7,Storyboards — rtovars @ 22.35

I’ve had little chance to work with Auto Layout since none of the projects I’m working on make use of this feature, as all of them are still targeted to iOS 5 or iOS 6 (I must really work on updating my own applications at least, but now it’s a transition time, so I don’t know what’s coming for me in my professional future). However, I’m working on an iOS side project for the company I work for, and this time I wanted to target iOS 7 exclusively. I also wanted to implement a Universal app since I’ll need the knowledge to implement the UI for another personal project I’ve left unattended for a long time (sigh!).

One of the things I wanted to do was to tackle the interface rotation bit, and so I started by creating two similar storyboard files (one for each platform) and then add rotation-aware logic into my iPad-targeted app. At the beginning everything worked fine, since Xcode 5 doesn’t force the implementation of Auto Layout constraints in order to work with the Simulator. However, there’s a note in Apple’s “Auto Layout Guide” stating the following:

Important: Although Xcode does not generate a warning or an error when you build a user interface that does not have appropriate constraints, you should not ship your application in such a state.”

Initial constraints created with fixed space to the nearest neighbor on the left and right sides.

Initial constraints created with fixed space to the nearest neighbor on the left and right sides.

Thus I started to implement said constraints using basically my intuition. I realized it would be harder this way, so I started reading the whole guide, despite of which I still was having troubles trying to lay out a simple image placed on the center of a UIScrollView, since Interface Builder kept calling my attention to the following warning: “Ambiguous Layout: Scrollable content size is ambiguous for “Scroll View”.” The visual outcome of my storyboard was basically an  image stretched out horizontally that obviously looked terrible.

First attempt at constraint implementation using fixed left and right space to nearest neighbor.

First attempt at constraint implementation using fixed left and right space to nearest neighbor.

I started doing a lot of research in StackOverflow (SO) and several other blogs and such, until I re-read the Apple documentation and I saw a reference to “spacer views“, although no explicit definition of a “spacer view” was given. I saw an example in SO in which a UIView was programmatically created and placed in the UI, so I started working on Interface Builder and adding simple UIViews with a clear color as background, one at each side of my image, and then basically leaving a leading and trailing space between them equal to 0, so the three views were placed back to back and the two spacer views touched the UIScrollView‘s left and right boundaries, also with a 0 spacing. One additional constraint that’s required so the spacer views expand and “hug” the center image is precisely to assign “equal widths” to the spacer views.

Improved constraints created with spacer views to the left and right sides of the logo.

Improved constraints created with spacer views to the left and right sides of the logo.

In the end I ran the app in the Simulator in both Portrait and Landscape orientations and everything worked fine, the center image remained pinned to the horizontal center and was not stretched to fulfill the previously set constraints that left a fixed space to the left and right of the image.

Final constraint implementation using spacer views.

Final constraint implementation using spacer views.

The bottom line is that a UIScrollView requires to have constraints for both its width and height, so it’ll be able to automatically calculate its content size.

Happy coding!

2014.04.24

Present modal view controllers in iOS 7

Filed under: iOS7,Storyboards — rtovars @ 11.43

Today I was having problems trying to present a modal view controller over my main UITabBarViewController, as I got the following error message:

Attempt to present <LoginViewController: 0x8bbc5f0> on <UITabBarController: 0x9a62d80> whose view is not in the window hierarchy!

Initially I added the code used to present the modal view controller to the viewDidLoad method of the view controller shown in the first tab, so that whenever the user launches the application and the first tab is shown, the modal view controller is immediately called to display a login dialog on the screen. However, when I ran the application on my Simulator, I only got the TabBar interface with the default first tab displayed on the screen, but the modal view controller was never called.

This is the code I was trying to use to call the modal view controller:

UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Storyboard" bundle:nil];
LoginViewController *loginController = [storyboard instantiateViewControllerWithIdentifier:@"LoginController"];
[self presentViewController:loginController animated:YES completion:nil];

I remembered I had already posted something related to this, and in effect I found my own answer to the same problem I was having on iOS 5 and 6, which obviously doesn’t apply anymore for iOS 7 as the presentModalViewController method has been deprecated.

Then I found this answer in StackOverflow, and comment number three mentioned the following: “I fixed this problem by taking out the present method of the viewDidLoad and put it in the viewDidAppear”. I tried this solution and my modal view controller was called and displayed aright. Again I forgot I shouldn’t display anything until the view controller is ready  to appear on the screen.

Keep coding!

2014.01.18

Problem converting old project with XIBs to use Storyboards

Filed under: iOS7,Objective-C,Storyboards — rtovars @ 23.46
Tags:

Hi there! It’s been a very long time since my last post, but with me moving back to the city where I started writing this blog after a stay of a year and a half in a bigger city with this foreign company, and starting again with my former employee, I haven’t had time to sit down and work on my own apps, but here I am again to document some strange behavior in iOS 7 for future reference.

OK, here’s the thing: I’m working on my first applications to update them to iOS 7 from the ground up, and this involves converting from MRC to ARC, and from the standard individual XIBs to Storyboards, among other things. For the latter process, I followed the steps outlined in this release note by Apple. However, whenever I tried to run my application on the iPhone Simulator, I always saw a blank screen after the initial launch image, and the output in Xcode’s Debug area displayed the following error message: “Application windows are expected to have a root view controller at the end of application launch”. I did some research but I didn’t find a specific reference to this issue when using Storyboards.

I did this conversion successfully some time ago in one of the commercial projects I worked for, and now that I remember, I had already tackled the same problem, but forgot to document it. Anyway, the real cause of the issue was that in the previous code the app delegate was a subclass of UIResponder, and according to the aforementioned release note: “the application delegate class inherits from UIResponder […] If you haven’t made use of this pattern in an existing application, there’s no need to adopt it for storyboards.” As too often happens, the problem was that I didn’t carefully read this note, and thus kept my app delegate as a subclass of UIResponder. When I double-checked code in my other project, I saw that indeed I had changed the superclass to NSObject, and voilà, problem solved! After this seemingly small change was implemented I ran the project in the Simulator and the initial view controller set up in my storyboard was visible on screen.

The moral of the story is this:

  1. When converting an old project with XIBs to Storyboards, also change the superclass from which the app delegate inherits from UIResponder to NSObject, and
  2. Always read carefully through the entire Apple documentation before coding, to avoid headaches when the recently implemented changes don’t seem to work!

OK, back to work, hopefully when I refactor to ARC there won’t be a lot of problems… I’ll keep you posted.

Happy coding!

2013.03.16

“A valid provisioning file for this executable was not found” issue

Filed under: General,Xcode — rtovars @ 18.56

I recently needed to install my application on an iPad at the office to do some tests. I physically connected the device to my MacPro and started building the application. Then, to my surprise, when the package was about to get installed, Xcode’s Organizer window displayed the following error message:
"A valid provisioning file for this executable was not found"

I checked my development provisioning profiles and I discovered one of them appeared with Invalid status in the iOS Provisioning Portal. I requested a new profile and tried to install, and again the same error message appeared. Then I saw that the new profile was not installed on the device, so I proceeded to select it from the Organizer’s Library, drag and drop it on the Provisioning Profiles section under the appropriate device name but nothing happened. Then I started looking for some answers on Google but none of the solutions I tried fixed the problem. I even requested new development certificates, and went through the whole process from square one but nothing worked.

I actually gave up on this problem and started doing something else on the Simulator, when I stumbled upon a logic problem and needed to check memory leaks and Zombie calls, so I fired up Instruments and when it was starting to load, it gave me a hint to what my other problem was all about. I didn’t take a screenshot of the actual message, but it indicated me that the Date and Time in my device were offset with respect to the host and this should be fixed before doing any actual debugging.

I then quickly proceeded to check the iPad’s General settings and I discovered the date was set one year in the future! I always set my iDevice’s Dates and Times in automatic mode so they’ll all be in sync, but since we’re sharing this device with other development teams I was not amazed at all that someone else changed the date either because of some experiments were being carried on or just as a bad joke. In any case I adjusted the date and then proceeded to install my application and what do you know? Everything went just fine!

It bothered me that fixing this problem took me a whole day, but at least I solved it on my own and was back on track to fix some nasty bugs reported by the QA Team.

I’ll proceed to post my answer in StackOverflow just in case someone else gets stuck with this.

Keep coding!

P.S. The link to my answer in StackOverflow is here.

2012.09.22

How to set a UITableView’s background in iOS6

Filed under: Design,Graphics,iOS6 — rtovars @ 21.50

Today I took some time to update my first iOS application to add a small feature, and while I was doing this I tested my app on the new iPhone 6.0 Simulator to see how it looked.

The first thing that called my attention was that the custom background pattern I use for the grouped UITableViews was missing and it was replaced by a gray striped background. I double-checked my code and I didn’t find anything strange in it, so I had to do some research and I found this answer in StackOverflow. I tried the first two lines and this time it worked like a charm, I was able to see again my custom background:

self.tableView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"patternBackground.png"]];
self.tableView.backgroundView = nil;

It’s weird how such a simple task as setting a grouped table background now takes two lines in iOS 6 instead of the single line I was using in both iOS 4 and 5.

Happy Xcoding!

2012.09.09

Problems with Core Data NSManagedObject faults

Filed under: Core Data,Objective-C — rtovars @ 19.23

Yesterday I was coding a UITableViewController for my third iPhone application and it all looked so simple as I just needed to retrieve some Core Data NSManagedObjects and display them in a table. Unfortunately when I started testing my code I saw that the second row in my table was always empty, in spite of the fact that the Core Data repository contained two entities with all the necessary data to create objects of this class.

Basically I have two objects with a relationship:

+------------+              +--------+
| SSCategory | <<-------->  | SSIcon |
|------------|              |--------|
| name       |              | name   |
| subtitle   |              | file   |
| ...        |              +--------+
+------------+

An SSCategory object has a one-to-one relationship with an SSIcon object (named icon), and an SSIcon object has a one-to-many relationship with multiple SSCategory objects (named category).

At first I thought the problem was in the Core Data repository itself, as I created some objects by hand using the excellent Core Data Editorcreated by Christian Kienle. I deleted the .sqlite file and started from scratch but the problem was still there.

I did some research on the Core Data fault mechanism and found some questions in StackOverflow, but none of them were of help, so I tried something on my own and I think I found a plausible explanation, albeit not a very technical one.

In my code there’s a table to show a list of SSCategory objects. When I fetch these objects from the repository I get an array with two faulted entities, which means they are empty objects:

<_PFArray 0xb87bfb0>(
<SSCategory: 0xb879610> (entity: SSCategory; id: 0xb87a1a0 <x-coredata://407108B7-288F-437B-B6F7-A3D65552D45C/SSCategory/p1> ; data: <fault>),
<SSCategory: 0xb87bed0> (entity: SSCategory; id: 0xb878c30 <x-coredata://407108B7-288F-437B-B6F7-A3D65552D45C/SSCategory/p2> ; data: <fault>)
)

Then, when the table is being populated with some of the SSCategory properties (like name or subtitle), the Core Data mechanism automatically retrieves the data and voilà, all the table rows show the right info.

When I need to create a new SSCategory object I must assign it a suitable SSIcon object which can be selected from another table, so I followed the same logic as before to create and load data for this table: I fetch all the SSIcon entities in the Core Data repository by themselves. This time in the populated table I saw two rows (as expected) but only the first one had data on it, the second one was blank.

Upon closer inspection I found that when fetching these SSIcon objects, only the first one had data, and the second one was always at fault, so nothing was retrieved from the repository and consequently the table row for this object didn’t have any info on it.

I looked for a way to force these objects to load their data, but it seems Core Data doesn’t provide a way to do this, as this behavior is automatic. Then I remembered I was only loading a single property of the SSCategory objects, i.e. its name instance variable, as I was leaving out other properties for later, since I don’t have all the icon images that I’m planning to use, for example. So what I did was to also load the SSIcon objects by accessing the related property (icon) and this time the icon list showed all the data, since the faults were fulfilled at a previous stage, namely when loading their owning SSCategory objects.

Now, the explanation I came up with is simply that at first when I was trying to fetch all the SSIcon objects on their own, the faults weren’t being fulfilled as they should be automatically fired when the related property of the owning object – in this case, an SSCategory instance – is called. As the second SSIcon entity isn’t yet called by any SSCategory entity, it remains at fault for the whole lifetime of the application.

Hope this makes sense. In any case, the right approach is to access all the pertinent parent object’s properties and then the child object’s data will be automatically loaded.

Keep coding!

2012.09.08

‘Unknown type name’ error happening in one of two similarly defined protocols

Filed under: Objective-C — rtovars @ 19.52

OK, so I’m working on my third iPhone application and I have a protocol that defines a delegate method to pass a value from a child view controller (the delegator) to its calling parent controller (the delegate).
The code looks like this:

#import <Foundation/Foundation.h>
@protocol SSSelectingCategory
@required
@property (nonatomic, strong) SSCategory *selectedCategory;
@end

This code compiles and works fine. However, when I had to create a similar protocol I found that it was throwing the Unknown type name 'SSIcon' error. The code is the same as in the first protocol, except for the names of the classes I’m using:

#import <Foundation/Foundation.h>
@protocol SSSelectingIcon <NSObject>
@required
@property (nonatomic, strong) SSIcon *selectedIcon;
@end

I double-checked my code but couldn’t find anything that could cause this error, so I decided to risk it and ask a question in StackOverflow, even when I already knew that the proper way to deal with this kind of error is to forward-declare the class like this:

#import <Foundation/Foundation.h>
@class SSIcon; // Forward-declare the class
@protocol SSSelectingIcon
@required
@property (nonatomic, strong) SSIcon *selectedIcon;
@end

Basically the answer states that my first protocol SSSelectingCategory finds the related class SSCategory in one of the classes that import or implement the protocol, but the second protocol SSSelectingIcon can’t find the related class SSIcon as it doesn’t appear in any of the importing or implementing classes. This is because the compiler compiles the .m files, which in turn include the .h files.

When I explicitly imported the SSIcon class in the class that implements the protocol, the error disappeared. However, the right way to go is to forward-declare the classes whenever they’re referred to.

Have fun coding!

2012.07.17

Problem displaying UIPickerView

Filed under: Objective-C,Prototype — rtovars @ 22.46

In my iPad application I want to show a UIPickerView in a UIViewController that’s pushed into a UINavigationController stack using the [self.navigationController pushViewController:countryComparisonController animated:NO] method.

Unfortunately the result I was getting was like this:

UIPickerView with no explicit frame setup

Apart from the fact that the width of the control is totally wrong, the picker wasn’t scrolling up nor down in spite of the fact that I was using the exact same code I used in another UIViewController, and all my outlets, delegates, and datasources were in place. The only difference was that the working UIPickerView was part of a root view controller, and the defective one was part of a view controller being pushed into a navigation stack.

After I spent a lot of time looking for an answer on the Internet, and having found nothing, I was suggested to setup the UIPickerView’s frame programmatically, like this:

-(void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    countryPickerView.frame = CGRectMake(20, 20, 250, 216);
}

And at last I got the result I wanted:
UIPickerView with explicit frame setup

I was really puzzled by this strange behavior as I even created the whole UIViewController+xib from scratch and I double-checked that everything needed was in place. It seems this is a problem in the iPad’s implementation of the control.

Anyway, my problem was solved and I was able to move on. Hope this helps you in case you find the same issue!

Next Page »

Blog at WordPress.com.