SwipeView icon indicating copy to clipboard operation
SwipeView copied to clipboard

How to modify controls inside a loaded XIB?

Open hafizrahman opened this issue 10 years ago • 14 comments

I am following your Controls Example project, because I want to emulate how the view for each SwipeView item is loaded from an XIB, instead of created programmatically.

Suppose I have added a label to itemView.xib, and I want to modify the text of this label. How and where do I go about to do this?

My XIB for the individual SwipeView item is called MTNNewsSingleSwipe and it has its own accompanying MTNNewsSingleSwipe.h and MTNNewsSingleSwipe.m files. The main view MTNNewsSingleSwipe.xib already uses 'MTNNewsSingleSwipe' as its custom class.

I suppose - (UIView *)swipeView:(SwipeView *)swipeView viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view is where I can modify the label's text, but I haven't managed to do it right yet. This is what I have so far:

- (UIView *)swipeView:(SwipeView *)swipeView viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
{

    if (!view)
    {
        NSArray *nibViews = [[NSBundle mainBundle] loadNibNamed:@"MTNNewsSingleSwipe" owner:self options:nil];
        view = [nibViews objectAtIndex:0];
        [view.testLabel setText:@"modify label text"]; /* Not working */
    }
    return view;
}

To explain the [view.testLabel setText:@"modify label text"]; part, I already set an outlet named testLabel inside MTNNewsSingleSwipe.h. For some reason, it is not detected and the text can't be set.

I feel like I'm missing something very obvious here. I would really appreciate it if you can give any pointers about this. Thank you in advance.

hafizrahman avatar Aug 15 '14 11:08 hafizrahman

@hafizrahman have you found a work around for this using xibs? I hating laying out project programmatically.

myusuf3 avatar Sep 16 '14 16:09 myusuf3

Sorry for not replying sooner. You were almost right; you would do it like this:

- (UIView *)swipeView:(SwipeView *)swipeView viewForItemAtIndex:(NSInteger)index reusingView:(MTNNewsSingleSwipe *)view
{

    if (!view)
    {
        //load the view if no view available for recycling
        view = [[[NSBundle mainBundle] loadNibNamed:@"MTNNewsSingleSwipe" owner:self options:nil] firstObject];
    }

    //set the label text (outside the "if (!view)" - very important)
    view.testLabel.text = @"modify label text";

    return view;
}

Note that I've specified the type of "reusingView" as MTNNewsSingleSwipe in the method declaration to avoid having to cast it to MTNNewsSingleSwipe when I set the testLabel.text.

nicklockwood avatar Sep 16 '14 16:09 nicklockwood

@nicklockwood what I am simply want to load a view controller with a xib interface with dynamic content?

myusuf3 avatar Sep 16 '14 17:09 myusuf3

I am doing the following currently.

- (UIView *)swipeView:(SwipeView *)swipeView viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
{
    TUSwipedViewController *viewController = [[TUSwipedViewController alloc] init];
    viewController.number.text = [_items[index] stringValue];
    return viewController.view;
}

I am sure I need to be loading in the xib some where but I am unsure as to where.

myusuf3 avatar Sep 16 '14 17:09 myusuf3

This ended up doing the trick

- (UIView *)swipeView:(SwipeView *)swipeView viewForItemAtIndex:(NSInteger)index reusingView:(UIView *)view
{
    TUSwipedViewController *viewController = nil;

    if (!view || !viewController)
    {
        //load the view if no view available for recycling
        viewController = [[TUSwipedViewController alloc] init];
        view = [[[NSBundle mainBundle] loadNibNamed:@"TUSwipedViewController" owner:viewController options:nil] firstObject];
    }

    //set the label text (outside the "if (!view)" - very important)
    viewController.number.text = [_items[index] stringValue];

    return view;

}

myusuf3 avatar Sep 16 '14 17:09 myusuf3

@nicklockwood you think it would be possible to stick a nav stack as each view in the swipe? that is what I am hoping to achieve. No luck so far.

So it would be something like swipe > new nav stack > push/pop viewcontrollers > swipe > new nav stack

myusuf3 avatar Sep 16 '14 18:09 myusuf3

This will work but it's the wrong approach. You do not need a view controller to load a view from a nib.

Instead of subclassing UIViewController and setting it as the file's owner in the nib, subclass UIView and set it as the class for the root view. Add the outlets to the view and bind them as normal. Use nil as the file's owner.

nicklockwood avatar Sep 16 '14 21:09 nicklockwood

Similarly, putting a navigation controller inside the carousel is wrong. Put the carousel inside the navigation controller, and then use delegate pattern to send messages from the carousel views to the carousel's view controller to push new controllers onto the stack.

nicklockwood avatar Sep 16 '14 21:09 nicklockwood

Think of iCarousel as like a tableView - you wouldn't use a separate view controller for each cell in your table, right? It's the same pattern.

nicklockwood avatar Sep 16 '14 21:09 nicklockwood

(Sorry, I meant SwipeView, obviously, not iCarousel - but the principle is the same)

nicklockwood avatar Sep 17 '14 08:09 nicklockwood

@nicklockwood Thanks for the awesome feedback! I am going to proceed and see where I get.

myusuf3 avatar Sep 17 '14 15:09 myusuf3

@nicklockwood I keep getting errors when i have the file owner set to nil.

Here is a gist describing what I have done.

https://gist.github.com/myusuf3/8aa14656ac23ed09be09

Right when it goes to get view I get this ''this class is not key value coding-compliant for the key''

myusuf3 avatar Sep 17 '14 16:09 myusuf3

Looks correct. What errors are you getting?

Btw, on further reflection, in your case it will be easier to set the switchToggled method on your carousel view controller, and use that as your file's owner. That way each view's switch will call the same method and you can decide what to do from there.

Everything else should remain as you have it.

nicklockwood avatar Sep 17 '14 17:09 nicklockwood

@nicklockwood it had to deal with how I was hooking up UIView managed to fix it. I also added cast to the correct type since UIView doesn't have a label or switchToggled.

I am now looking into doing the navigation stack stuff, you got a second on IRC or something. I would totally appreciate it.

myusuf3 avatar Sep 17 '14 17:09 myusuf3