Problem with moving a view

Discussion in 'iOS Programming' started by cjhsb, Sep 17, 2008.

  1. cjhsb macrumors newbie

    Joined:
    Sep 17, 2008
    Location:
    London
    #1
    Firstly, just a quick hello to the community!

    I'm new this week to IPhone app development, and Macs in general; my obj c skills are new (it's been some 15 years since I dabbled in C), but I have many years in some other languages (ColdFusion, SQL etc).

    I've read a lot of recommended documentation, and jumped in the deep end with my first application; perhaps somewhat silly but that's how I've learned languages in the past!

    Anyway, on with my problem - no doubt it's something utterly basic but I've been pulling my hair out for 2 days trying to find (or work out) an answer.

    I'm trying to get a loaded image to move in response to a basic finger touch; I have borrowed the code from the "moveme" sample application and I have tried to integrate it into my existing project (which interface has been implemented through IB), however I am stuck on the one error and cant resolve it. TubeMap is the name of the object view holding the image (which is bigger than the view that holds it), which I have made of the class MoveMeView, which I believe is a subclass of UIImageView.

    MoveMeView.h

    MoveMeView.m
    On compile, 1 error and 2 warnings

    - tubeMap with a "comparison of distinct Objective-C types lacks a cast" (both warnings)
    and more importantly
    tubeMap.center = location; gives "request for member 'center' in something not a structure or union".

    Now I think that means I'm trying to set a variable in my instance of TubeMap that doesn't exist, but it should be the centre of the image. So no doubt I'm doing something basic incorrectly. If anyone could help me out (a fix would be nice but an explanation of what I've done wrong would be even more helpful) I would be most grateful.

    Thanks in advance!
     
  2. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #2
    The compiler will have marked the offending rows in your editor window. That should tell you where to fix it. It would help us if you told us which lines it highlighted.

    Anyway...

     
  3. PhoneyDeveloper macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #3
    Add this to the top of MoveMeView.m

    #import "TubeMap.h"

    gcc's error messages suck dead donkey (well you know). This error means that gcc doesn't know what TubeMap is.
     
  4. cjhsb thread starter macrumors newbie

    Joined:
    Sep 17, 2008
    Location:
    London
    #4
    Thanks both of you for getting back so promptly; this has been very helpful to aid my understanding a little more but I'm still having kittens!

    Sorry I will do that next time; however you estimated correctly where they were.

    I wanted to compare it with the instance of TubeMap (so if the screen is touched within this view then the method does something). If I change tubeMap to if ([touch view] != (UIView *tubeMap)) I get a syntax error before 'tubeMap', which obviously means I'm still not understanding something fundamental.

    Ah thanks - at least I was right about what the error was trying to say, even if I don't get why. Am I right in assuming that the class and superclasses don't have a center property because it's the instance of the view that does? I'm trying to get the instance of TubeMap that is on the screen to re-center under the user's touch, displaying the part of the graphic in the view that is currently clipped offscreen.

    Just FYI when I do reference it to self it compiles, but then doesn't display in the simulator anyway....and I thought this would be an easy way to learn...:D

    Sadly there is no TubeMap.h - TubeMap is a view that is made by ForthView.xib, which is one of 4 nibs that I've built to house 4 tab options of the app. It loads fine without including moveme.m and .h in the project, but when I change the final error in moveme.m from tubeMap.center to self.center the view is white-screen (no crash) for that tab - I think at this point IB is actually causing me a lot of pain as if I'd just written it programatically it would of been a huge amount clearer.

    ForthView.xib
    Code:
    <?xml version="1.0" encoding="UTF-8"?>
    <archive type="com.apple.InterfaceBuilder3.CocoaTouch.XIB" version="7.02">
    	<data>
    		<int key="IBDocument.SystemTarget">512</int>
    		<string key="IBDocument.SystemVersion">9D34</string>
    		<string key="IBDocument.InterfaceBuilderVersion">670</string>
    		<string key="IBDocument.AppKitVersion">949.33</string>
    		<string key="IBDocument.HIToolboxVersion">352.00</string>
    		<object class="NSMutableArray" key="IBDocument.EditedObjectIDs">
    			<bool key="EncodedWithXMLCoder">YES</bool>
    			<integer value="7"/>
    		</object>
    		<object class="NSArray" key="IBDocument.PluginDependencies">
    			<bool key="EncodedWithXMLCoder">YES</bool>
    			<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
    		</object>
    		<object class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
    			<bool key="EncodedWithXMLCoder">YES</bool>
    			<object class="IBProxyObject" id="372490531">
    				<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
    			</object>
    			<object class="IBProxyObject" id="975951072">
    				<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
    			</object>
    			<object class="IBUIImageView" id="979351559">
    				<reference key="NSNextResponder"/>
    				<int key="NSvFlags">292</int>
    				<string key="NSFrameSize">{240, 128}</string>
    				<reference key="NSSuperview"/>
    				<bool key="IBUIOpaque">NO</bool>
    				<bool key="IBUIClearsContextBeforeDrawing">NO</bool>
    				<int key="IBUIContentMode">2</int>
    				<bool key="IBUIMultipleTouchEnabled">YES</bool>
    				<object class="NSCustomResource" key="IBUIImage">
    					<string key="NSClassName">NSImage</string>
    					<string key="NSResourceName">LUM.png</string>
    				</object>
    			</object>
    		</object>
    		<object class="IBObjectContainer" key="IBDocument.Objects">
    			<object class="NSMutableArray" key="connectionRecords">
    				<bool key="EncodedWithXMLCoder">YES</bool>
    				<object class="IBConnectionRecord">
    					<object class="IBCocoaTouchOutletConnection" key="connection">
    						<string key="label">view</string>
    						<reference key="source" ref="372490531"/>
    						<reference key="destination" ref="979351559"/>
    					</object>
    					<int key="connectionID">11</int>
    				</object>
    			</object>
    			<object class="IBMutableOrderedSet" key="objectRecords">
    				<object class="NSArray" key="orderedObjects">
    					<bool key="EncodedWithXMLCoder">YES</bool>
    					<object class="IBObjectRecord">
    						<int key="objectID">0</int>
    						<object class="NSArray" key="object" id="360949347">
    							<bool key="EncodedWithXMLCoder">YES</bool>
    						</object>
    						<reference key="children" ref="1000"/>
    						<nil key="parent"/>
    					</object>
    					<object class="IBObjectRecord">
    						<int key="objectID">-1</int>
    						<reference key="object" ref="372490531"/>
    						<reference key="parent" ref="360949347"/>
    						<string type="base64-UTF8" key="objectName">RmlsZSdzIE93bmVyA</string>
    					</object>
    					<object class="IBObjectRecord">
    						<int key="objectID">-2</int>
    						<reference key="object" ref="975951072"/>
    						<reference key="parent" ref="360949347"/>
    					</object>
    					<object class="IBObjectRecord">
    						<int key="objectID">7</int>
    						<reference key="object" ref="979351559"/>
    						<reference key="parent" ref="360949347"/>
    						<string key="objectName">TubeMap</string>
    					</object>
    				</object>
    			</object>
    			<object class="NSMutableDictionary" key="flattenedProperties">
    				<bool key="EncodedWithXMLCoder">YES</bool>
    				<object class="NSMutableArray" key="dict.sortedKeys">
    					<bool key="EncodedWithXMLCoder">YES</bool>
    					<string>-1.CustomClassName</string>
    					<string>-2.CustomClassName</string>
    					<string>7.CustomClassName</string>
    					<string>7.IBEditorWindowLastContentRect</string>
    					<string>7.IBPluginDependency</string>
    				</object>
    				<object class="NSMutableArray" key="dict.values">
    					<bool key="EncodedWithXMLCoder">YES</bool>
    					<string>FirstViewController</string>
    					<string>UIResponder</string>
    					<string>MoveMeView</string>
    					<string>{{752, 803}, {240, 128}}</string>
    					<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
    				</object>
    			</object>
    			<object class="NSMutableDictionary" key="unlocalizedProperties">
    				<bool key="EncodedWithXMLCoder">YES</bool>
    				<object class="NSArray" key="dict.sortedKeys">
    					<bool key="EncodedWithXMLCoder">YES</bool>
    				</object>
    				<object class="NSMutableArray" key="dict.values">
    					<bool key="EncodedWithXMLCoder">YES</bool>
    				</object>
    			</object>
    			<nil key="activeLocalization"/>
    			<object class="NSMutableDictionary" key="localizations">
    				<bool key="EncodedWithXMLCoder">YES</bool>
    				<object class="NSArray" key="dict.sortedKeys">
    					<bool key="EncodedWithXMLCoder">YES</bool>
    				</object>
    				<object class="NSMutableArray" key="dict.values">
    					<bool key="EncodedWithXMLCoder">YES</bool>
    				</object>
    			</object>
    			<nil key="sourceID"/>
    			<int key="maxID">11</int>
    		</object>
    		<object class="IBClassDescriber" key="IBDocument.Classes">
    			<object class="NSMutableArray" key="referencedPartialClassDescriptions">
    				<bool key="EncodedWithXMLCoder">YES</bool>
    				<object class="IBPartialClassDescription">
    					<string key="className">FirstViewController</string>
    					<string key="superclassName">UIViewController</string>
    					<object class="IBClassDescriptionSource" key="sourceIdentifier">
    						<string key="majorKey">IBProjectSource</string>
    						<string key="minorKey">Classes/FirstViewController.h</string>
    					</object>
    				</object>
    				<object class="IBPartialClassDescription">
    					<string key="className">MoveMeView</string>
    					<string key="superclassName">UIImageView</string>
    					<object class="IBClassDescriptionSource" key="sourceIdentifier">
    						<string key="majorKey">IBProjectSource</string>
    						<string key="minorKey">Classes/MoveMeView.h</string>
    					</object>
    				</object>
    				<object class="IBPartialClassDescription">
    					<string key="className">UIImageView</string>
    					<string key="superclassName">UIView</string>
    					<object class="IBClassDescriptionSource" key="sourceIdentifier">
    						<string key="majorKey">IBUserSource</string>
    						<string key="minorKey"/>
    					</object>
    				</object>
    			</object>
    		</object>
    		<int key="IBDocument.localizationMode">0</int>
    		<string key="IBDocument.LastKnownRelativeProjectPath">ITube.xcodeproj</string>
    		<int key="IBDocument.defaultPropertyAccessControl">3</int>
    	</data>
    </archive>
    
    Any further thoughts guys?
     
  5. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #5
    Your UIView cast is wrong. It should be:

    Code:
    ((UIView *) tubeMap)
    not

    Code:
    (UIView* tubeMap)
    What is TubeMap? A custom UIView subclass? If so there has to be code for this to exist. Simply changing the class to this in IB will not work: you need to have IB create the skeleton files and implement the class.
     
  6. cjhsb thread starter macrumors newbie

    Joined:
    Sep 17, 2008
    Location:
    London
    #6
    Ah thanks - I knew I was missing something fundamental about how to cast!

    That still returns an error, but I think were actually getting to the problem now, and it looks like my lack of understanding about IB.

    TubeMap is the name which I gave the view object in ForthView.xib and then changed it's class type from UIImageView to MoveMeView. Since it compiles ok and runs fine when I remove movemeview.h and .m and revert the class to UIImageView, I had assumed that the IB file created an object instance with that name, which must have a class, so I have been trying to get movemeview to control the instance of TubeMap. I hope that makes sense somehow...?
     
  7. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #7
    Style note: don't start instance variable names with a capital: everyone else will read that as a class name.

    What do you mean by "TubeMap is the name which I gave the view object". Objects don't have names.
     
  8. cjhsb thread starter macrumors newbie

    Joined:
    Sep 17, 2008
    Location:
    London
    #8
    I thought it was a class name.

    Ok, I'm not using the right terminology here I think and causing more confusion; my apologies.

    In IB you can drag in a UIImageView and set some properties. I did this, and named it TubeMap. I then set a graphic file that is bigger than the view to load into it, aspect fill. I set it's ref outlet view to file's owner and compiled my project. It works as intended, displaying part of the image onscreen when the appropriate tab was pressed to load this nib file.

    I then decided I wanted to try to understand how touch worked, so I attempted to alter the movemeview example to manage a user's touch in this view to move the graphic on the screen to show areas that were currently clipped by the static image.

    So I tried to alter movemeview.h and .m to refer to the UIImageview I had created in my nib file (named TubeMap), and in IB I set it's type from UIImageView to MoveMeView, as I thought MoveMeView was a custom subclass of UIImageview and would thus use any MoveMeView methods "automatically" (ie touchesBegan and touchesMoved to move TubeMap).

    This to me seemed logical, but clearly it's not :confused: I hope that explains what I was trying to do and can highlight my basic assumption error(s)!
     
  9. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #9
    If TubeMap is a class then you need implementation files (.m and .h) for it. But I am still confused about this "and named it TubeMap". Views don't have names. You can't assign a string to a view as it's name and then use that as some sort of global identifier for the view.

    Post a screenshot of where you set the name. I suspect you set the classname of the object. This means you have told IB that you will be using a custom UIView subclass for this view: you must provide code for this custom subclass.
     
  10. cjhsb thread starter macrumors newbie

    Joined:
    Sep 17, 2008
    Location:
    London
    #10

    Ah ok then this is where my assumption is falling down; I assumed you could!

    Attached SS is where I am setting the name; how would I reference it then if not by name?

    BTW thanks very much for your continued help; it's very much appreciated!
     

    Attached Files:

  11. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #11
    No attachement :confused:

    Edit: and now there is :)

    Edit again: that name is only usable from Interface Builder (I think). It certainly doesn't translate to a global variable in XCode. It may be possible to programatically step through the view tree querying names, or even ask a UIWindow for an object by name like you can by tag.

    The normal way to get a reference to a view would be to have an IBOutlet in the file owner (custom class) that will get linked to the object it's connected to when the nib/xib is loaded.

    Also as a side-note you do know you can't distribute the tube map image without paying a license fee to TFL right?

    Yet another edit: UIView is just like it's NS counterparty: you can search for subviews by tag but there is no corresponding by name search. That name is only really to help searches in IB I think.
     
  12. cjhsb thread starter macrumors newbie

    Joined:
    Sep 17, 2008
    Location:
    London
    #12
    Yes, sorry, realised then had to take a call then did it :)
     
  13. cjhsb thread starter macrumors newbie

    Joined:
    Sep 17, 2008
    Location:
    London
    #13
    Ahhh thanks very much indeed; that explains why I felt like I was banging my head against a tree! I'll do some more research and try to implement it via an IBOutlet then.

    And yes - the project is a home one to teach me rather than to distribute - though if I ever finish the whole app I might think about drawing my own map image :D
     
  14. cjhsb thread starter macrumors newbie

    Joined:
    Sep 17, 2008
    Location:
    London
    #14
    Another day, another problem with this it seems!

    Ok, I read up and implemented an IBOutlet and custom class as suggested. Pleased to say the project now compiles and does not crash so thanks very much indeed - however, when I click on the tab to load up this view in the simulator, it doesn't draw the view.

    No doubt again it's something fundamental on my part, but despite spending the evening last night trying to spot it, I can't see why. Any further help along my road of learning therefore again much appreciated!

    moveme.h

    Code:
    #import <UIKit/UIKit.h>
    
    @class MoveMeView;
    
    @interface MoveMeView : UIView {
    		IBOutlet UIImageView *mapPosition;
    }
    
    @property (nonatomic, retain) UIImageView *mapPosition;
    
    @end
    
    moveme.m
    Code:
    #import "MoveMeView.h"
    
    @implementation MoveMeView
    
    @synthesize mapPosition;
    
    - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    	
    	// We only support single touches, so anyObject retrieves just that touch from touches
    	UITouch *touch = [touches anyObject];
    	
    	if ([touch view] != mapPosition) {
    				return;
    	}
    }
    
    
    - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    	
    	UITouch *touch = [touches anyObject];
    	
    	// If the touch was in the tubeMap, move the tubeMap accordingly
    	if ([touch view] == mapPosition) {
    		CGPoint location = [touch locationInView:self];
    		mapPosition.center = location;
    		
    		return;
    	}
    }
    
    
    
    
    - (void)dealloc {
    	[mapPosition release];
    	[super dealloc];	
    }
    
    @end
    
    and finally a ss of the view with its settings in IB...

    Many thanks!
     

    Attached Files:

  15. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #15
    MoveMeView must either have a draw method or a subview. Is the view that contains the map added as a subview?

    Also please use code tags!
     
  16. cjhsb thread starter macrumors newbie

    Joined:
    Sep 17, 2008
    Location:
    London
    #16
    Sorry about the code wrappers - I was fixing them as you were posting - your just too fast responding for me to even fix my post errors! :D

    Ok, it doesn't, but that brings me back to my initial quandary I think then about accessing views, which was why I was trying to name it in IB - from your reply earlier, am I right in assuming i should be adding [contentView addSubview: *<id_of_the_view_holding_the_image_file>]; (rather than a string holding a name reference) after the synthesize line to add it as a subview? If so, how do I find out what that id number should be?

    Thanks to your very kind help I think I may be starting to find may way through this forest!
     
  17. robbieduncan Moderator emeritus

    robbieduncan

    Joined:
    Jul 24, 2002
    Location:
    London
    #17
    I was assuming you'd add the subview in IB. If you are trying to add it in code you need a pointer to that object as per usual. How you get that pointer depends largely on where the object is created. If you are creating it in code you have the pointer: it's up to you how you pass this reference around to get it where you need it. If you create the view in IB but don't add it as a subview then an IBOutlet would be the easiest way.

    Personally in my iPhone projects so far I've given up on using IB at all: I just create the entire interface programatically.
     
  18. cjhsb thread starter macrumors newbie

    Joined:
    Sep 17, 2008
    Location:
    London
    #18
    Ah ok yes I did add it in IB; I think I'm starting to understand now. Equally, I think my hatred of IB is growing at the same rate. Many thanks again for helping me along my first steps!
     

Share This Page