Register a SA Forums Account here!
JOINING THE SA FORUMS WILL REMOVE THIS BIG AD, THE ANNOYING UNDERLINED ADS, AND STUPID INTERSTITIAL ADS!!!

You can: log in, read the tech support FAQ, or request your lost password. This dumb message (and those ads) will appear on every screen until you register! Get rid of this crap by registering your own SA Forums Account and joining roughly 150,000 Goons, for the one-time price of $9.95! We charge money because it costs us money per month for bills, and since we don't believe in showing ads to our users, we try to make the money back through forum registrations.
 
  • Post
  • Reply
Luigi Thirty
Apr 30, 2006

Emergency confection port.

Gordon Cole posted:

Why would you want to replace every int with an NSNumber? That would introduce a bunch of overhead for no reason. Typically the only time I ever use them is when I need to store numbers in a container class that only stores objects.

I did a direct port of a Java class before I knew what I was doing and suddenly I'm converting all the ints to NSWhatever every time I want to interact with it because I'm a moron :shepface:

Oh yeah! Xcode's layout editor actually works unlike Eclipse + ADT. That's cool too.

Luigi Thirty fucked around with this message at 09:08 on Feb 28, 2012

Adbot
ADBOT LOVES YOU

stray
Jun 28, 2005

"It's a jet pack, Michael. What could possibly go wrong?"

Ender.uNF posted:

Well if you don't want to use CoreData and the NSFetchedResultsController then just store the items in an NSArray and use one section and the row as the index into the array. Trying to support sections, sorting, etc without using CoreData is just a good way to get confused and random crashes IMHO, but you would essentially use an NSArray to store the items and another NSArray where the contents of the array is an NSNumber pointing into the original array. If you use sections then you need another layer of indirection for the sections.
Is it worth it to just skip ahead and learn Core Data?

duck monster
Dec 15, 2004

Luigi Thirty posted:

Coming from a C and Java background Xcode should come with a swear jar for every time you use int instead of NSNumber. :smithicide:

The Objective-C syntax is weird as hell to me but I like it better than Android development if only from a "the operating system is not hacked together from a bunch of little pieces glued together into the rough shape of a cube" aspect.

Stick with it. Other than ObjC's [NSObjectName reallyVerboseMethodNameThing: AlsoMaybeThis: ohGodWhyNot: ] sort of verbosity, its a really charming stack when you get the hang of it.

duck monster
Dec 15, 2004

stray posted:

Is it worth it to just skip ahead and learn Core Data?

Sure if you like boilerplate and hair-pulling problems with schema upgrades.

That said , core data is kind of neat.

lord funk
Feb 16, 2004

duck monster posted:

Stick with it. Other than ObjC's [NSObjectName reallyVerboseMethodNameThing: AlsoMaybeThis: ohGodWhyNot: ] sort of verbosity, its a really charming stack when you get the hang of it.

Yeah, I cringe a bit now when I see things like new widget(0, 12, this, "WHAT", 4.5, 0, 0, "HUH")

Small White Dragon
Nov 23, 2007

No relation.
Well I'm looking forward to seeing a retina screen iPad simulator.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

stray posted:

Is it worth it to just skip ahead and learn Core Data?

No.

echobucket
Aug 19, 2004

Small White Dragon posted:

Well I'm looking forward to seeing a retina screen iPad simulator.

I'm not sure what kind of monitor you would display that on. The Retina display would be 2048x1536 and a 27" iMac is 2560 by 1440.

I suppose it would work in landscape, but not in portrait ;)

xzzy
Mar 5, 2009

This says to me that Apple should release a Retina Cinema Display. :aaaaa:

Bob Morales
Aug 18, 2006


Just wear the fucking mask, Bob

I don't care how many people I probably infected with COVID-19 while refusing to wear a mask, my comfort is far more important than the health and safety of everyone around me!

Stupid Objective-C question, but I'm having trouble on when to make a new object and stuff like that.

Should I do it for everything I can?

Only one object per .m file, right?

Can I make a C-style struct that contains NSObjects or is that just a bad idea?

If I were to do an object called Albums, I'd put that in Album.m and then do something like:
code:
@interface Album : NSObject {
  NSString *name;
  NSArray *songTitles
  NSNumber *price;
  NSImage *albumArt;
}
Or should these be defined some other way?

All the C++ I did was 'C using iostreams' so I'm never worked a lot with objects.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Bob Morales posted:

Stupid Objective-C question, but I'm having trouble on when to make a new object and stuff like that.

Should I do it for everything I can?

First off, you're talking about a class, not an object.

When to make a new class is one of those questions that'll get you five different answers from five different people. In general, I prefer more classes to fewer, because in Objective-C classes are nicer to use than structs or C primitives.

quote:

Only one object per .m file, right?

A typical Objective-C header file (.h file) will have an interface for one object, and a protocol for that object's delegate if appropriate. Then the @implementation will go into the .m file. But the compiler doesn't give a poo poo and I'm perfectly happy putting a few closely-related class definitions in the same header file. If I have a class that I only use internally to that .m file, I'll hide the @interface in the .m file too.

quote:

Can I make a C-style struct that contains NSObjects or is that just a bad idea?

You're more than welcome to put Objective-C objects into structs. If you're using automated reference counting, you'll need to tag them __unsafe_unretained.

Usually, though, I find it's more useful to put objects in a relevant collection (array, dictionary) or make a new class that holds the objects as properties.

quote:

If I were to do an object called Albums, I'd put that in Album.m and then do something like:
code:
@interface Album : NSObject {
  NSString *name;
  NSArray *songTitles
  NSNumber *price;
  NSImage *albumArt;
}
Or should these be defined some other way?

That'll work great. You'd put the @interface in Album.h and the @implementation in Album.m.

However, here's what I'd do:

code:
@interface Album : NSObject

@property (copy) NSString *name;
@property (copy) NSArray *songTitles;
@property (retain) NSNumber *price;
@property (retain) NSImage *albumArt;

@end
Then I'd @synthesize each of those properties in the @implementation in Album.m. If any of these instance variables weren't meant for public consumption, I'd move the @property to a class extension in Album.m (also where I put the signatures for private methods).

Properties give you handy stuff for free, work with C types and Objective-C objects, and (imho) have no downside. I've basically stopped defining my own instance variables.

duck monster
Dec 15, 2004

Can someone tell me where the gently caress the iphone simulator saves screenshots.

This stupid anti-feature where apple seems to have decided save dialogs arent needed anymore is continuously loving me on this god drat operating system.

I will be gobsmacked if this poo poo isnt fixed in mountain lion, because its a useability clusterfuck.

Built 4 Cuban Linux
Jul 15, 2007

i own america

duck monster posted:

Can someone tell me where the gently caress the iphone simulator saves screenshots.

This stupid anti-feature where apple seems to have decided save dialogs arent needed anymore is continuously loving me on this god drat operating system.

I will be gobsmacked if this poo poo isnt fixed in mountain lion, because its a useability clusterfuck.

Desktop.

duck monster
Dec 15, 2004

Built 4 Cuban Linux posted:

Desktop.

Nope!

PT6A
Jan 5, 2006

Public school teachers are callous dictators who won't lift a finger to stop children from peeing in my plane

duck monster posted:

Nope!

On my system, it's in ~/Library/Application Support/Developer/Shared/Xcode/Screenshots. ~/Library is hidden in file chooser dialogs and the Finder because, as I mentioned earlier, Apple wants you to suffer. Hit Shift+Cmd+G in Finder to get there.

Or right-click the image in the XCode Organizer window and select "Show in Finder." I think you have to move them somewhere else before you can do something like edit or upload them, whichever way you choose to get to that folder.

duck monster
Dec 15, 2004

PT6A posted:

On my system, it's in ~/Library/Application Support/Developer/Shared/Xcode/Screenshots. ~/Library is hidden in file chooser dialogs and the Finder because, as I mentioned earlier, Apple wants you to suffer. Hit Shift+Cmd+G in Finder to get there.

Or right-click the image in the XCode Organizer window and select "Show in Finder." I think you have to move them somewhere else before you can do something like edit or upload them, whichever way you choose to get to that folder.

fffuuuuuuuuuuccckkkk its just like using an ipad! We're in the future now man!

Also on the subject of apple retardedness, I note that years after I first filed an apple bug that the iphone emulator breaks mac-os application installers , its still breaking mac-os application installers. Good work apple! Nice to see those bug-reports you close are being read!

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



Not to be all Apple fanboy here, but non-powerusers have nothing to do in Library so it's absolutely fine that it's hidden by default. If you want it visible you can go like this in the terminal:

code:
chflags nohidden ~/Library
Or for once-in-a-while access, you can do open ~/Library or use the Go > Go to Folder... menu in the Finder or probably multiple other options.

duck monster
Dec 15, 2004

Carthag posted:

Not to be all Apple fanboy here, but non-powerusers have nothing to do in Library so it's absolutely fine that it's hidden by default. If you want it visible you can go like this in the terminal:
As long as they dont use any applications written prior to lion, sure.

quote:

code:
chflags nohidden ~/Library
Or for once-in-a-while access, you can do open ~/Library or use the Go > Go to Folder... menu in the Finder or probably multiple other options.

I'm pretty sure 99% of everyone has the chflags thing as the first thing they do upon installing lion, since a tonne of apps actually store user save files in there, since apple prior to lion actually recomended it. (Hence why its in user space) I mean gently caress, as discussed, plenty of *current* lion apps including from apple store user created files in ~/library/application support/app/

duck monster fucked around with this message at 05:08 on Feb 29, 2012

Thoom
Jan 12, 2004

LUIGI SMASH!
If I wanted to get a really deep understanding of how OS X works, would reading Mac OS X Internals: A Systems Approach still be a good idea (given that it was written in the PPC/Tiger era and a lot has changed since then), or is there a more up to date resource?

Edit: Someone else recommended OS X and iOS Kernel Programming as a more up-to-date, albeit less comprehensive, alternative. Would that be a good choice?

Thoom fucked around with this message at 06:54 on Feb 29, 2012

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



I hadn't actually changed Library visbility since updating to Lion, I use it rarely enough that I'm probably in the Terminal when I need it anyway.

Besides, even if the majority of users on these forums unhide Library, I doubt it's like that outside. I was talking about users like my parents, ie 99% of real world users, the ones who don't even know that you can select a different folder than the one the app suggests/Documents.

Anyway Thoom, It's been a while since I read it, but it should be alright. The basic architecture of OS X hasn't changed drastically since Tiger - the majority of changes have been in higher-level stuff like new Cocoa frameworks (the Core * stuff).

PT6A
Jan 5, 2006

Public school teachers are callous dictators who won't lift a finger to stop children from peeing in my plane

Carthag posted:

Not to be all Apple fanboy here, but non-powerusers have nothing to do in Library so it's absolutely fine that it's hidden by default. If you want it visible you can go like this in the terminal:

code:
chflags nohidden ~/Library
Or for once-in-a-while access, you can do open ~/Library or use the Go > Go to Folder... menu in the Finder or probably multiple other options.

Wow, that's quite helpful. I didn't know that could be done.

Is there any reason Apple decided to use chflags instead of the standard UNIX starts-with-a-dot hidden file?

carry on then
Jul 10, 2010

by VideoGames

(and can't post for 10 years!)

Probably because changing the name would break every single application that writes to ~/Library.

PT6A
Jan 5, 2006

Public school teachers are callous dictators who won't lift a finger to stop children from peeing in my plane

carry on then posted:

Probably because changing the name would break every single application that writes to ~/Library.

Yes, but if they were writing files to ~/Library that they expected the user to be able to find, which evidently even xCode was doing, then that folder should not be hidden. Then, new applications could write to ~/.Library based on the idea that it would be hidden.

This would be slightly confusing, though. I'm not entirely sure why they didn't leave well enough alone. If they were worried about people getting into it and loving something up, then they could've had a warning like Windows used to (still does?) in Program Files.

LP0 ON FIRE
Jan 25, 2006

beep boop
I'm in one of these moments where I'm doing something completely retarded but I'm absolutely stumped. I'm just trying to load my html into my UIWebView with the correct baseURL so that I can use relative paths.

code:
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSURL *baseURL = [NSURL fileURLWithPath:path];
    [webView loadHTMLString:@"tour.html" baseURL:baseURL];
It just shows the text "tour.html" inside my UIWebView..

Froist
Jun 6, 2004

Forgive me for what may be an stupid question.

I've got a few years experience writing mobile apps (mainly Symbian) and about 6 months ago I started learning iOS development for work, and have now made a couple of business-y iPad apps. I've had an idea for a game I want to make in my free time, but having never made a game before I'm not really sure how to start.

My idea's for a game similar to Bejewelled (yeah, we need another one of those) so luckily it takes physics engines/complex input/3D rendering out of the equation. I was also going for a very minimal graphic design, similar to Async Corp with (probably) manually drawn objects rather than image textures which would usually be managed by a game engine.

Given these factors, and my inexperience with any game engines, how would you approach developing this? I see I have 3 options:
  • Man up and learn how one of these engines works, probably cocos2d (unless there are any other suggestions?)
  • Create my UI with lots of custom UIViews, one for each 'block' in the puzzle plus others for the other UI elements, and manipulate these as the game is played
  • Create one big custom UIView that does all the drawing for the whole game grid (I think this is a bad option)

Obviously these last 2 options lock me into UIKit and would make porting it to any other platforms far more tricky further down the line. At the moment I don't have any plans for this, but I do have an Android tablet (and know java, though nothing Android specific), so it would be neat if there was an engine I could use with zero modification (aside from the framework requirements) on both that and my iPhone.

Am I an idiot for even considering just using UIViews for this, or is it reasonable given I won't require most of the things I'd expect a game engine provides you with? As it's the method I know off the bat it may be easier for prototyping and just seeing how my idea plays out, and basic UIKit animations should cover the style I'm going for.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

LP0 ON FIRE posted:

I'm in one of these moments where I'm doing something completely retarded but I'm absolutely stumped. I'm just trying to load my html into my UIWebView with the correct baseURL so that I can use relative paths.

code:
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSURL *baseURL = [NSURL fileURLWithPath:path];
    [webView loadHTMLString:@"tour.html" baseURL:baseURL];
It just shows the text "tour.html" inside my UIWebView..

code:
NSURL *urlToTourHTML = ...;
NSError *error;
NSString *tourHTML = [NSString stringWithContentsOfURL:urlToTourHTML
                                              encoding:NSUTF8StringEncoding
                                                 error:&error];
if (tourHTML)
    [webView loadHTMLString:tourHTML];
else
    handle error
or use -loadRequest: on the UIWebView.

eeenmachine
Feb 2, 2004

BUY MORE CRABS

Froist posted:

Forgive me for what may be an stupid question.

I've got a few years experience writing mobile apps (mainly Symbian) and about 6 months ago I started learning iOS development for work, and have now made a couple of business-y iPad apps. I've had an idea for a game I want to make in my free time, but having never made a game before I'm not really sure how to start.

My idea's for a game similar to Bejewelled (yeah, we need another one of those) so luckily it takes physics engines/complex input/3D rendering out of the equation. I was also going for a very minimal graphic design, similar to Async Corp with (probably) manually drawn objects rather than image textures which would usually be managed by a game engine.

Given these factors, and my inexperience with any game engines, how would you approach developing this? I see I have 3 options:
  • Man up and learn how one of these engines works, probably cocos2d (unless there are any other suggestions?)
  • Create my UI with lots of custom UIViews, one for each 'block' in the puzzle plus others for the other UI elements, and manipulate these as the game is played
  • Create one big custom UIView that does all the drawing for the whole game grid (I think this is a bad option)

Obviously these last 2 options lock me into UIKit and would make porting it to any other platforms far more tricky further down the line. At the moment I don't have any plans for this, but I do have an Android tablet (and know java, though nothing Android specific), so it would be neat if there was an engine I could use with zero modification (aside from the framework requirements) on both that and my iPhone.

Am I an idiot for even considering just using UIViews for this, or is it reasonable given I won't require most of the things I'd expect a game engine provides you with? As it's the method I know off the bat it may be easier for prototyping and just seeing how my idea plays out, and basic UIKit animations should cover the style I'm going for.

Definitely go with cocos2d.

Carthag Tuek
Oct 15, 2005

Tider skal komme,
tider skal henrulle,
slægt skal følge slægters gang



LP0 ON FIRE posted:

I'm in one of these moments where I'm doing something completely retarded but I'm absolutely stumped. I'm just trying to load my html into my UIWebView with the correct baseURL so that I can use relative paths.

code:
    NSString *path = [[NSBundle mainBundle] bundlePath];
    NSURL *baseURL = [NSURL fileURLWithPath:path];
    [webView loadHTMLString:@"tour.html" baseURL:baseURL];
It just shows the text "tour.html" inside my UIWebView..

You're having the webView show the actual HTML string "tour.html", not the file by that name. It's for doing things like loadHTMLString:@"<html>blahblah</html>"

You want something like:

[webView setMainFrameURL:[[NSBundle mainBundle] pathForResource:@"tour" oFType:@"html"]];

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Froist posted:

Am I an idiot for even considering just using UIViews for this, or is it reasonable given I won't require most of the things I'd expect a game engine provides you with? As it's the method I know off the bat it may be easier for prototyping and just seeing how my idea plays out, and basic UIKit animations should cover the style I'm going for.

Not an idiot at all. If frame rates start to suffer, feel free to look into your other choices.

One such choice is to go the next level down and look at Core Animation. CALayer is quite a bit more lightweight than UIView, so you'll probably be able to a) make things simpler and b) get more of them on screen animating at once.

Bob Morales
Aug 18, 2006


Just wear the fucking mask, Bob

I don't care how many people I probably infected with COVID-19 while refusing to wear a mask, my comfort is far more important than the health and safety of everyone around me!

Froist posted:

Forgive me for what may be an stupid question.

I've got a few years experience writing mobile apps (mainly Symbian) and about 6 months ago I started learning iOS development for work, and have now made a couple of business-y iPad apps. I've had an idea for a game I want to make in my free time, but having never made a game before I'm not really sure how to start.

My idea's for a game similar to Bejewelled (yeah, we need another one of those) so luckily it takes physics engines/complex input/3D rendering out of the equation. I was also going for a very minimal graphic design, similar to Async Corp with (probably) manually drawn objects rather than image textures which would usually be managed by a game engine.

Given these factors, and my inexperience with any game engines, how would you approach developing this? I see I have 3 options:
  • Man up and learn how one of these engines works, probably cocos2d (unless there are any other suggestions?)
  • Create my UI with lots of custom UIViews, one for each 'block' in the puzzle plus others for the other UI elements, and manipulate these as the game is played
  • Create one big custom UIView that does all the drawing for the whole game grid (I think this is a bad option)

Obviously these last 2 options lock me into UIKit and would make porting it to any other platforms far more tricky further down the line. At the moment I don't have any plans for this, but I do have an Android tablet (and know java, though nothing Android specific), so it would be neat if there was an engine I could use with zero modification (aside from the framework requirements) on both that and my iPhone.

Am I an idiot for even considering just using UIViews for this, or is it reasonable given I won't require most of the things I'd expect a game engine provides you with? As it's the method I know off the bat it may be easier for prototyping and just seeing how my idea plays out, and basic UIKit animations should cover the style I'm going for.

You could just have at it with OpenGL.

Or, make your own simple game engine:



Contrary to the title, it's not a 'beginner' book.

eeenmachine
Feb 2, 2004

BUY MORE CRABS

Bob Morales posted:

You could just have at it with OpenGL.

Or, make your own simple game engine:



Contrary to the title, it's not a 'beginner' book.

I'm one of the authors on that book. Wouldn't recommend it over online cocos2d tutorials (or a cocos2d centered book).

xelfer
Nov 27, 2007

What's new, Buseycat? woa-aah, woa-aah, woa-aah

eeenmachine posted:

I'm one of the authors on that book. Wouldn't recommend it over online cocos2d tutorials (or a cocos2d centered book).

Speaking of - http://www.raywenderlich.com/tutorials has some great cocos2d tutorials, I'm working through them now.

Simulated
Sep 28, 2001
Lowtax giveth, and Lowtax taketh away.
College Slice
OK so let's get started with RestKit mapping.

First of all you will be starting with the RKObjectManager. That class provides the overall layer that sits on top of RKClient and handles object mapping.

code:
[RKObjectMapping setDefaultDateFormatters:[NSArray arrayWithObject:
    [RKDotNetDateFormatter dotNetDateFormatter]]];
[RKObjectMapping setPreferredDateFormatter:
    [RKDotNetDateFormatter dotNetDateFormatter]];

RKObjectManager setSharedManager:[RKObjectManager objectManagerWithBaseURL:@"https://myserver.example/api/v1/"]];
XObjectManager.objectStore = [self createObjectStore];
XObjectManager.mappingProvider = [self getMappingProvider];
XObjectManager.client.username = @"user";
XObjectManager.client.password = @"heythere";
XObjectManager.serializationMIMEType = RKMIMETypeJSON;
[self setObjectRoutes:XObjectManager];
First we tell RestKit what date/time formatters we want to use. In my case I am using WCF so I need the. Net-style formatter. I actually recommend that for everyone because it is the only 100% accurate yet standard JSON way to transmit dates/times but if your platform prefers ISO or whatever go ahead but it has a high chance of biting you in the rear end at some point when you start dealing with timezones and international stuff. (It helps that the JSON spec doesn't address this at all).

Next we new up a manager with a base URL so all our other calls can be relative. The manager creates its own RKClient internally (not using the regular RKClient sharedClient which is nice if we need to mix-and-match use of them both). We set the serialization type to JSON which means when we PUT/POST we will send JSON data… we could use form encoding which would submit the data as a regular HTML-style form with key-value pairs (and passing an NSDictionary for the values) but why bother? Just let it reverse the serialization of your classes and post back as JSON.

The objectStore bit involves CoreData so we'll get to that later. The first real step is to setup our object mappings. Object Mappings can be a bitch to get right because JSON is so free-form and everyone does it differently so don't get frustrated if it doesn't work at first.

I am going to demonstrate several things in this one bit of code which is based on a real project I am working on right now (most examples I see out there are laughably simple stuff like twitter feeds that are zero help in the real world). Since I am using CoreData I am using RKManagedObjectMappings but the principal is the same for RKObjectMapping in a non-CoreData scenario.

code:
__strong static RKObjectMappingProvider *_mappingProvider = nil;
- (RKObjectMappingProvider *)getMappingProvider
{
    if(!_mappingProvider) 
    {
        _mappingProvider = [RKObjectMappingProvider mappingProvider];
        
        //note types
        RKManagedObjectMapping *noteTypeMap = [RKManagedObjectMapping mappingForClass:[NoteType class]];
        noteTypeMap.primaryKeyAttribute = @"noteTypeId";
        [noteTypeMap mapAttributes:@"canGrantDemerits", @"name", @"isSystem", @"noteTypeId", @"canGrantMerits", nil];
        [_mappingProvider addObjectMapping:noteTypeMap];
        
        //notesubtypes
        RKManagedObjectMapping *noteSubTypeMap = [RKManagedObjectMapping mappingForClass:[NoteSubType class]];
        noteSubTypeMap.primaryKeyAttribute = @"noteSubTypeId";
        [noteSubTypeMap mapAttributes:@"noteSubTypeId", @"defaultDemerits", @"defaultMerits", 
               @"isSystem", @"name", @"noteTypeId", nil];

        [noteSubTypeMap hasOne:@"noteType" withMapping:noteTypeMap];
        [noteSubTypeMap connectRelationship:@"noteType" withObjectForPrimaryKeyAttribute:@"noteTypeId"];
        //because noteType contains the noteSubTypes we connect that here
        [noteTypeMap hasMany:@"noteSubTypes" withMapping:subTypeMap]; 

        [_mappingProvider addObjectMapping:noteSubTypeMap];
                
        //subjectType
        RKManagedObjectMapping *subjectTypeMap = [RKManagedObjectMapping mappingForClass:[SubjectType class]];
        subjectTypeMap.primaryKeyAttribute = @"subjectTypeId";
        [subjectTypeMap mapAttributes:@"subjectTypeId", @"name", @"color", nil];
        [_mappingProvider addObjectMapping:subjectTypeMap];
        
        
        //subject
        RKManagedObjectMapping *subjMap = [RKManagedObjectMapping mappingForClass:[Subject class]];
        subjMap.primaryKeyAttribute = @"subjectId";
        [subjMap mapAttributes:@"subjectId", @"isPace", @"name", @"subjectTypeId", nil];
        [_mappingProvider addObjectMapping:subjMap];

        [subjMap hasOne:@"subjectType" withMapping:subjectTypeMap];
        [subjMap connectRelationship:@"subjectType" withObjectForPrimaryKeyAttribute:@"subjectTypeId"];
OK first of all note that I am only constructing the map once for the life of the application. I do it this way because my app lets you connect to multiple systems so it resets the shared RKObjectManager when you connect but the map says the same. If you only ever connect to one known back-end then you can do away with the static field stuff.

First you create classes (NoteType, NoteSubType) that will hold the data you want to store. For numbers I recommend NSNumber. Strings are obvious. If an object contains a set of sub objects that will be an NSSet or NSArray.

If the names of properties are the same in JSON and Objective-C you can just call mapAttributes:, otherwise you will need to call mapKeyPathsToAttributes: and specify the JSON name then the property name for each pair. Feel free to mix-and-match. It does support KVC so you can use proper key paths both on the JSON side (to collapse nested objects into one super object) or the Objective-C side (to push values from one object into a sub object).

In this case since I am using CoreData, I specify the primary keys of my objects then specify the hasOne:withMapping: or hasMany:withMapping: relationships but that would just tell RestKit that I expect each NoteSubType to contain its NoteType but the NoteTypes contain NoteSubTypes, and infinitely recurse to a crash. Instead calling connectRelationship:withObjectForPrimaryKeyAttribute: will make it check CoreData using the property indicated to find the corresponding object with that primary key. Thus so long as I load the objects in the correct order the relationships will all just hook up on the CoreData side.

For NoteType and NoteSubType the JSON in this case is structured like so: [{noteTypeId:1, -other props-, noteSubTypes:[{noteSubTypeId:5, name:blah},{noteSubTypeId:6, name:blah2}]}]. Each NoteType contains the list of NoteSubTypes related to it so I have to indicate that relationship.

In contrast, a SubjectType does *not* contain its subjects in the JSON so

code:
        //student
        RKManagedObjectMapping *studentMap = [RKManagedObjectMapping mappingForClass:[Student class]];
        studentMap.primaryKeyAttribute = @"studentId";
        [studentMap mapAttributes:@"studentId", @"fullName", @"status", @"photoHash", nil];
        [_mappingProvider addObjectMapping:studentMap];     
How can the most important class in my application not have more mapping setup than this? :psyduck: Simple - since I only map the reverse property of the one-to-many relationships my student object actually doesn't have anything to map. That is generally the pattern you should follow - have your JSON objects carry foreign keys on them (e.g. integers) and map from that side of the relationship.

code:
          
        //note
        RKManagedObjectMapping *noteMap = [RKManagedObjectMapping mappingForClass:[Note class]];
        noteMap.primaryKeyAttribute = @"noteId";
        [noteMap mapAttributes:@"noteId", @"createdBy", @"createdOn",  
               @"noteSubTypeId", @"noteTypeId", @"studentId", @"text", nil];
        [_mappingProvider addObjectMapping:noteMap];
        [noteMap hasOne:@"student" withMapping:studentMap];
        [noteMap connectRelationship:@"student" withObjectForPrimaryKeyAttribute:@"studentId"];
        [noteMap mappingForRelationship:@"student"].reversible = NO;

        [noteMap hasOne:@"noteType" withMapping:noteTypeMap];
        [noteMap connectRelationship:@"noteType" withObjectForPrimaryKeyAttribute:@"noteTypeId"];
        [noteMap mappingForRelationship:@"noteType"].reversible = NO;

        [noteMap hasOne:@"noteSubType" withMapping:noteSubTypeMap];
        [noteMap connectRelationship:@"noteSubType" withObjectForPrimaryKeyAttribute:@"noteSubTypeId"];
        [noteMap mappingForRelationship:@"noteSubType"].reversible = NO;

        [_mappingProvider setSerializationMapping:[noteMap inverseMapping] forClass:[Note class]];

    }
    return  _mappingProvider;
}
Now let's look at an object where I need to create, update, and/or delete the object from my application. How is that accomplished? Serialization mapping. The magic line setSerializationMapping:forClass: will take care of it for you and as a bonus you can just call inverseMapping on the input map.

The big thing to note here is that I set the various relationships to reversible=NO so they aren't included in the inverse map, otherwise trying to PUT a Note would end up sending the associated student, which itself would include all the other details including the note, and infinite loop again.


So how would you hook this up to CoreData? Well you basically just model the JSON in CoreData instead of plain classes then use Xcode to generate the entity classes automatically. The only other step is to connect the objectStore:

code:
- (RKManagedObjectStore *)createObjectStore
{
    return [RKManagedObjectStore objectStoreWithStoreFilename:@"MyCoreDataModel.sqlite" 
                                        usingSeedDatabaseName:nil 
                                           managedObjectModel:XAppDelegate.model 
                                                     delegate:nil];
}
Pretty simple yes? If you bundle a pre-populated database with your app you can pass that in usingSeedDatabaseName: and it will make a copy of that seed data as your starting point. Next step is to deal with routing which is just an automated way of calculating URLs for you:

code:
- (void)setObjectRoutes:(RKObjectManager *)manager
{
    RKObjectRouter *router = manager.router;
        
    [router routeClass:[Goal class] toResourcePath:@"Goals/:goalId" forMethod:RKRequestMethodGET];
    [router routeClass:[Goal class] toResourcePath:@"Goals/:goalId" forMethod:RKRequestMethodPUT];
    [router routeClass:[Goal class] toResourcePath:@"Goals/:goalId" forMethod:RKRequestMethodDELETE];
    [router routeClass:[Goal class] toResourcePath:@"Goals" forMethod:RKRequestMethodPOST];
    
    
    [router routeClass:[Note class] toResourcePath:@"Notes/:noteId" forMethod:RKRequestMethodPUT];
    [router routeClass:[Note class] toResourcePath:@"Notes/:noteId" forMethod:RKRequestMethodDELETE];
    [router routeClass:[Note class] toResourcePath:@"Notes" forMethod:RKRequestMethodPOST];
}
Here we setup some routes for the associated HTTP verbs. The :XYZ syntax just has it insert the corresponding property value from your object into the URL.


Lastly, what does it look like to use RKObjectManager and get responses?
code:
- (void)doStuff
{
    //get list of objects example
    [XObjectManager loadObjectsAtResourcePath:@"NoteTypes" 
                                objectMapping:[XObjectManager.mappingProvider objectMappingForClass:[NoteType class]]  
                                     delegate:self];
    //delete example
    [XObjectManager deleteObject:myObj delegate:self];
}
- (void)objectLoader:(RKObjectLoader*)objectLoader didFailWithError:(NSError*)error
{
    Class objClass = objectLoader.objectMapping.objectClass;
    NSString *className = NSStringFromClass(objClass);
    NSLog(@"Failed to load %@: %@", className, error);
    [self showError:[NSString stringWithFormat:@"Error trying to load data from the system:\n%@", error] isError:YES];
}
- (void)objectLoader:(RKObjectLoader*)objectLoader didLoadObjects:(NSArray*)objects
{   
    if(objectLoader.isDELETE)
    {
        [XObjectManager.objectStore.managedObjectContext deleteObject:objectLoader.sourceObject];
        [XObjectManager.objectStore save];
    }
    else if(objectLoader.objectMapping.objectClass == [NoteType class])
    {
         //at this point the note types have been saved to CoreData    
    }
}
In my case I am using WCF and my JSON is structured such that it cannot automatically determine the mapping for responses so with the loadObjects I am manually giving the map to use. There are some facilities where you can say if the top-level JSON is an object with property "noteTypes":[] then automatically use the NoteTypes mapping. I recommend checking out the existing RestKit tutorials for more detailed information about all the esoteric JSON mapping stuff and routing stuff but I can almost guarantee that if it is valid JSON then RestKit can map it, no matter how annoying the representation is.

You can always access the object that initiated a DELETE, PUT, POST, or single GET via objectLoader.sourceObject. If you are using CoreData and primary keys correctly that object will also be the single object in the objects array as RestKit will update the existing CoreData object rather than creating a new one. It is important to keep the idea of object lifetime in your client separate from the server. Just because a DELETE call succeeds doesn't mean it suddenly disappeared from CoreData or memory. You could leave "tombstoned" deleted objects all over the place if you wanted.

Anytime the call results in a response object that can be successfully mapped in CoreData mode the associated CoreData object will be updated with the new values. If the primary key fields match the existing object will be updated, otherwise a new object will be created (e.g.: leave the primary key nil for a POST and have your POST call return the newly inserted object. This will result in the object you new'ed up having its primary key field filled in after the POST succeeds, along with any other server-side provided fields). If you are doing a DELETE you must currently handle the delete from the Object Store yourself so watch out for that. If you take advantage of NSFetchedResults controller's delegate then you can have really nice automatic updating of your UI when the background requests succeed. In fact I sometimes update a table cell with a "saving" or spinner image when I fire off the request and forget about it - the NSFetchedResults delegate will fire when RestKit updates CoreData in the background, triggering a reload of that table row which will then clear the text/image.


A few more quick words - You don't have to go 100% at any layer of your application. You can have entities/properties in CoreDaa that aren't part of the RestKit mapping. You can have a class that isn't an NSManagedObject but give it a map (e.g.: data you only want to work with live in memory but not persist to the store). If you have a method that doesn't really return any JSON or requires binary data in a multi-part form you can use RKClient along side RKObjectManager.

Part of what they are working on now is improvements to the cache support. The idea is that you provide an NSFetchRequest that corresponds to a specific URL and if any objects are not returned by the server but exist in the request they will be deleted (because they were already deleted by the server). I am handling this manually at the moment but I plan on switching over as soon as they get that fully tested and stable.

I also see people asking about how to do off-line editing, deleting, etc and you can definitely do that it just takes a little bit of extra work on your part. Add some flags to your CoreData model for every object type: isDeleted, isPending. When connectivity is re-established you can check and send a DELETE for any objects where isDeleted = true. The mapping/serialization will ignore those properties in CoreData so it should work just fine. Upon success you can then delete the object from your store. For isPending, issue a PUT or POST for each of those objects and on success you can set isPending=NO.

LP0 ON FIRE
Jan 25, 2006

beep boop

pokeyman posted:

code:
NSURL *urlToTourHTML = ...;
NSError *error;
NSString *tourHTML = [NSString stringWithContentsOfURL:urlToTourHTML
                                              encoding:NSUTF8StringEncoding
                                                 error:&error];
if (tourHTML)
    [webView loadHTMLString:tourHTML];
else
    handle error
or use -loadRequest: on the UIWebView.

Carthag posted:

You're having the webView show the actual HTML string "tour.html", not the file by that name. It's for doing things like loadHTMLString:@"<html>blahblah</html>"

You want something like:

[webView setMainFrameURL:[[NSBundle mainBundle] pathForResource:@"tour" oFType:@"html"]];

Thank you. I ended up going with
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"tour" ofType:@"html"]isDirectory:NO]]];

And then I had many hardships with adding folders the correct way and trying to figure out why my javascript wouldn't work in my UIWebView.

I hope someone reading this will save themselves some time in case they don't know:

1.) When dragging folders in that you want a UIWebView to reference as offline data, make sure you click the "Create folder references for any added folders" radio button.

2.) Any javascript files on the root level of resources (not in a folder) will be compiled by Xcode. In most cases you don't want this to happen if the UIWebView depends on using it just as a website would. You need to drag the javascript files from your Compile Sources in Build Phases into Copy Bundle Resources.

Now everything works great!

Doc Block
Apr 15, 2003
Fun Shoe

LP0 ON FIRE posted:

Thank you. I ended up going with
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL fileURLWithPath:[[NSBundle mainBundle] pathForResource:@"tour" ofType:@"html"]isDirectory:NO]]];

And then I had many hardships with adding folders the correct way and trying to figure out why my javascript wouldn't work in my UIWebView.

I hope someone reading this will save themselves some time in case they don't know:

1.) When dragging folders in that you want a UIWebView to reference as offline data, make sure you click the "Create folder references for any added folders" radio button.

2.) Any javascript files on the root level of resources (not in a folder) will be compiled by Xcode. In most cases you don't want this to happen if the UIWebView depends on using it just as a website would. You need to drag the javascript files from your Compile Sources in Build Phases into Copy Bundle Resources.

Now everything works great!

If you don't need JavaScipt or anything really complex but just want the ability to show formatted text with images and links, and still be able to have it fit the look of your app then give DTCoreText a shot.

Way better performance-wise that having to pull in a UIWebView.

Bob Morales
Aug 18, 2006


Just wear the fucking mask, Bob

I don't care how many people I probably infected with COVID-19 while refusing to wear a mask, my comfort is far more important than the health and safety of everyone around me!

:argh: Xcode is such a crash-happy piece of poo poo :argh:

LP0 ON FIRE
Jan 25, 2006

beep boop

Doc Block posted:

If you don't need JavaScipt or anything really complex but just want the ability to show formatted text with images and links, and still be able to have it fit the look of your app then give DTCoreText a shot.

Way better performance-wise that having to pull in a UIWebView.

Cool, good to note. I'm actually using KRPano made from Panotour Pro to view virtual tours. The challenge was doing this offline with UIWebView so that I can include it in an app that can do other things than just view the virtual tours. Other people are using GoodReader, which is lame to me because that means I can't use my virtual tours in an app that runs offline.

Mr. Glass
May 1, 2009
Anyone know if it's possible to pass a variable number of values to a Core Image kernel? The best idea I've come up with so far is to have the CIFilter subclass generate the filter code on the fly, but that seems needlessly complex.

coaxmetal
Oct 21, 2010

I flamed me own dad
Has anyone packaged an (ios) xcode project for open source release? I need to do that for a project (that I didn't write) and I'm not sure if there are convention I should follow or anything. Also it uses a proprietary lib, I need to not include that, maybe just the header or something.

If someone has experience or an example of this that would be cool

Adbot
ADBOT LOVES YOU

CRIP EATIN BREAD
Jun 24, 2002

Hey stop worrying bout my acting bitch, and worry about your WACK ass music. In the mean time... Eat a hot bowl of Dicks! Ice T



Soiled Meat
I'm a C coder by trade, but I've been working on an iOS project lately and I'm looking to overcome some problems that seem to be creeping up on my application.

First and foremost, this project uses Core Data. Core Data so far has been great, and my data model works great. However, I'm looking at cleaning up the application a bit to simplify my view controllers.

  1. Obviously it makes sense for your NSManagedObjectContext to be passed from view controller to view controller. That way if you are entering a state where you are about to make some changes to back out of, you can pass a child of the current view controllers NSManagedObjectContext to the next view controller. It doesn't make sense to have a global NSManagedObjectContext available to anyone if I am passing it to my child view controllers, correct?
  2. When creating an entity, you obviously need this NSManagedObjectContext. However, the method requires you to pass an entity descriptor. Where is the best place for this code to exist? Does it make sense to have a factory that is constructed with the NSManagedObjectContext to create the objects?
  3. I have some data that is unique to the user that is stored in Core Data (fetched from a server, stored locally), and I have different ways of organizing it that is used in multiple places. Does it make sense in this case to have a singleton object that exposes these different organized data?

  • 1
  • 2
  • 3
  • 4
  • 5
  • Post
  • Reply