Testing equality of UIViews, clarification needed - objective-c

I am having trouble testing equality on the Views that are set up in my project.
This is a long post, please bear with me. I have 3 separate views set up as part of the same XIB.
Each view is connected to File Owner (UIViewController) via an IBOutlet
The owner itself is a UIViewController
#interface PuzzleViewController : UIViewController {
Inside the FileOwner views are declared as:
IBOutlet Puzzle1 *p1;
IBOutlet Puzzle2 *p2;
IBOutlet Puzzle3 *p3;
#property (nonatomic, retain) IBOutlet Puzzle1 *p1;
#property (nonatomic, retain) IBOutlet Puzzle2 *p2;
#property (nonatomic, retain) IBOutlet Puzzle3 *p3;
Additionally i have
UIView *currentPuzzleView;
#property (nonatomic, retain) UIView *currentPuzzleView;
In .m file, upon initialization, i declare current view to be p1
[self setCurrentPuzzleView:p1];
Later, i would like to check if current view is in fact p1. This comparison fails.
if ([[self currentPuzzleView] isEqual:p1]) {
Additionally this fails as well
if ([self currentPuzzleView] == p1) {
Why is this?

Because you are using different classes for the equality test (UIView and Puzzle1). Your currentPuzzleView should be a pointer to one of those three classes Puzzle1 Puzzle2 Puzzle3. If you definitely need to use three different classes for those puzzle views, try adding tags to them and change
#property (nonatomic, retain) UIView *currentPuzzleView;
to
int currentPuzzleViewTag;
set it to 1 upon viewDidLoad: and change the tag to appropriate when different views are selected.

It's just a hunch but perhaps p1 is nil 'upon initialization'. It really depends on where you set currentPuzzleView to p1. It could be that the outlet points to nothing (yet).

Related

cocoa-Why there is an IBOutlet and a property that are of the same name?

I'm new to objective-c. When I'm reading some source code written by others, I encountered a problem.
I found that there is
IBOutlet NSPopover *popover;
as well as
#property NSPopover *popover;
PopoverViewController.h
#import <Foundation/Foundation.h>
#import <Cocoa/Cocoa.h>
#import "TimerPopoverViewController.h"
#class TimerLogic;
#class TimerInfo;
#interface TimerPopoverDelegate : NSObject <NSPopoverDelegate> {
#private
IBOutlet NSPopover *popover;
IBOutlet NSWindow *detachWindow;
IBOutlet TimerPopoverViewController *viewController;
}
#property NSPopover *popover;
- (void)showPopover:(id)sender timerInfo:(TimerInfo *)timerInfo;
#end
I think they are different variables. However, I can't figure out what do they do?
As far as I'm concerned, the IBOutlet is to show a popover.
But what does the #property does?
This is either very old code or written in a very old (and now discouraged) style. The IBOutlet here is declaring an instance variable (ivar). The #property is declaring a property that is backed by the instance variable. In modern ObjC you should implement it this way:
PopoverViewController.h
#import <Cocoa/Cocoa.h>
#class TimerInfo;
// Things declared here are public
#interface TimerPopoverDelegate : NSObject <NSPopoverDelegate>
// You could leave this here if it is required by other parts of the program,
// but other parts of the program really shouldn't require it. See below.
// #property (nonatomic, readonly, weak) NSPopover *popover;
- (void)showPopover:(id)sender timerInfo:(TimerInfo *)timerInfo;
#end
PopoverViewController.m
// Generally avoid importing local headers into the .h unless you have to.
#import "TimerPopoverViewController.h"
// Things declared here are private. This is much better than the old #private.
#interface TimerPopoverDelegate ()
#property (nonatomic, readwrite, weak) IBOutlet NSPopover *popover;
#property (nonatomic, readwrite, weak) IBOutlet NSWindow *detachWindow;
#property (nonatomic, readwrite, weak) IBOutlet TimerPopoverViewController *viewController;
#end
(Currently popover is public, but you should avoid exposing an IBOutlet that way. Outside objects should not directly touch a view controller's outlets.)

IBInspectable property values not updating in xib

I'm running into a minor complication using IBInspectable properties and not sure if it might have something to do with my xibs and xib usage. I'm trying to reuse a custom control between multiple view controllers. The control is a custom tab manager:
The IBInspectable Attributes are configured in this xib as: First, Second, Third.
Here is the corresponding code for the header file.
IB_DESIGNABLE
#interface TabContainerView : NSView
#property (nonatomic, strong) IBOutlet NSView *view;
#property (weak) IBOutlet TabContentView *contentView;
#property (weak) IBOutlet TabView *firstTab;
#property (weak) IBOutlet TabView *secondTab;
#property (weak) IBOutlet TabView *thirdTab;
#property (nonatomic, strong) IBInspectable NSString *tabOneText;
#property (nonatomic, strong) IBInspectable NSString *tabTwoText;
#property (nonatomic, strong) IBInspectable NSString *tabThreeText;
#end
#import "TabContainerView.h"
#interface TabContainerView ()
#property (nonatomic, strong) NSMutableArray *tabsArray;
#property (nonatomic, assign) NSInteger selectedTabIndex;
#property (weak) IBOutlet NSTextField *tabOneTextField;
#property (weak) IBOutlet NSTextField *tabTwoTextField;
#property (weak) IBOutlet NSTextField *tabThreeTextField;
#end
#implementation TabContainerView
#pragma mark Init
- (id)initWithFrame:(NSRect)frameRect {
NSString* nibName = NSStringFromClass([self class]);
self = [super initWithFrame:frameRect];
if (self) {
if ([[NSBundle mainBundle] loadNibNamed:nibName
owner:self
topLevelObjects:nil]) {
[self configureView];
}
}
return self;
}
#pragma mark Configure View
- (void)configureView{
[self.view setFrame:[self bounds]];
[self addSubview:self.view];
self.tabOneTextField.stringValue = self.tabOneText;
self.tabTwoTextField.stringValue = self.tabTwoText;
self.tabThreeTextField.stringValue = self.tabThreeText;
}
#end
This works fine in the TabContainerView.xib without issue. Now when I attempt to use this control in two different view controllers, I run into problems. Both of my view controllers are also loaded from Xibs.
In view controller 1 I have something like this:
In view controller 1 I've subclassed the custom view to the TabContainerView subclass which works just fine when I run the application. I've also changed the text to be specific for this view controller. List, Map, Filter are the IBInspectable property values for view controller one. In view controller 2 (not shown), I've done the exact same thing, however different IBInspectable property values specific for view controller 2. However, when I run the application the values never update and always stay as First, Second, and Third. I'm not sure if there is something I'm doing that's causing this problem but any help or tips would be appreciated. (IBDesignable seems to give me a lot of warnings where it breaks and not sure if maybe it's just loading the last saved value for the xib.)
Have you imported #import "TabContainerView.h" in controller 2 .h file.

How to manipulate IBOutlet UIImageView objects in series using For Loop

# of Images are placed in a View using Storyboard.
I want to manipulate them programmatically using a For loop. But couldn't find how to?
Currently i am using the following code:
#property (weak, nonatomic) IBOutlet UIImageView *img_level2;
#property (weak, nonatomic) IBOutlet UIImageView *img_level3;
#property (weak, nonatomic) IBOutlet UIImageView *img_level4;
#property (weak, nonatomic) IBOutlet UIImageView *img_level5;
#property (weak, nonatomic) IBOutlet UIImageView *img_level6;
#property (weak, nonatomic) IBOutlet UIImageView *img_level7;
...
...
...
_img_level2.image = [_img_level2.image convertToGrayscale];
_img_level3.image = [_img_level3.image convertToGrayscale];
_img_level4.image = [_img_level4.image convertToGrayscale];
_img_level5.image = [_img_level5.image convertToGrayscale];
_img_level6.image = [_img_level6.image convertToGrayscale];
_img_level7.image = [_img_level7.image convertToGrayscale];
Now instead of writing them line by line i want to use a for loop. Because this procedure might be called multiple times for sizing and positioning.
Please advice, thanks!
Instead of having each of the buttons as its own UIButton property, you can define an outlet collection, which is essentially an array that you'll be able to treat exactly as you want (for example, loop over all of its items).
How do you do that? Simple:
In your code, replace all of the IBOutlet UIImageView... lines with:
IBOutletCollection(UIImageView) NSMutableArray *imgLevels;
On InterfaceBuilder, give each of your UIImageViews a different tag that will match its index in the IBOutletCollection.
And, finally, when you connect the objects on your .xib or storyboard file, you'll notice it will appear on the Referencing Outlet Collections section instead of the Referencing Outlets as you're used to.
Now you have an array that you can use to loop over your IBOutlets exactly as you would loop a "regular" NSArray. Good Luck!

How to add a UIView to an UIAlertView?

I have to create a custom AlertView with a view that contain some label. I create the .h and .m of CustomAlert
this is the CustomAlert.h.
#import <Foundation/Foundation.h>
#interface CustomAlert: UIView
#property (nonatomic, weak) IBOutlet UILabel *ok;
#property (nonatomic, weak) IBOutlet UILabel *ok1;
#property (nonatomic, weak) IBOutlet UILabel *ok2;
#property (nonatomic, weak) IBOutlet UILabel *ok3;
#property (nonatomic, weak) IBOutlet UILabel *ok4;
#property (nonatomic, weak) IBOutlet UILabel *ok5;
#end
and this is the CustomAlert.m.
#import "CustomAlert.h"
#implementation CustomAlert
#synthesize ok = _ok;
#synthesize ok1 = _ok1;
#synthesize ok2 = _ok2;
#synthesize ok3 = _ok3;
#synthesize ok4 = _ok4;
#synthesize ok5 = _ok5;;
#end
I also create the xib with just a view and i connect the label with all the "ok".
Now, i want to add this View to an AlertView with just an Ok button. How can i do it? I want to use it with ios 7 and 6.
Thanks!!
In iOS 7 you should not munge a UIAlertView like this - and there is no need, because thanks to custom view transitions you can make your own small presented view in front of your interface, so that it looks and acts like a UIAlertView but can contain anything you like.
I've written an online tutorial on how to do this:
http://programming.oreilly.com/2014/01/transcending-uialertview-on-ios-7.html
And there's a downloadable github project that goes with it:
https://github.com/mattneub/custom-alert-view-iOS7

IBOutlets defined in controller's .h file are not visible in Inspector

I am creating a iPad app, using XCode4 and Storyboard. I have the exact same app on a iPhone, which works just fine. I copied all of the controller's .h and .m files to the new iPad app. There are NO build errors. I am using custom cells in several UITableViews, with prototype cells.
I have 4 IBOutlets defined in a .h file, which is included in the UIView controller's .h file. I'm trying to connect the IBOutlets to the objects in the prototype cells, but when I click on the controller, the objects don't appear in the Inspector.
Any idea why?
UPDATE: here is the code for the SiteListingCell.h.
#import <UIKit/UIKit.h>
#interface SiteListingsCell : UITableViewCell {
}
#property (nonatomic, strong) IBOutlet UILabel *staLabel;
#property (nonatomic, strong) IBOutlet UILabel *descLabel;
#property (nonatomic, strong) IBOutlet UILabel *dateLabel;
#end
Make sure the class of the object you're trying to connect is set correctly in IB: