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
HiriseSoftware
Dec 3, 2004

Two tips for the wise:
1. Buy an AK-97 assault rifle.
2. If there's someone hanging around your neighborhood you don't know, shoot him.
Is there any way to detect if there are "too many" touches on the device? I know that the iPhone supports 5 touches and the iPad has 11. I've got a soon-to-be-released kids app and of course my 3-year old finds a bug when he puts too many fingers on the screen. For example, on the iPhone, if I put 5 fingers on the screen at once, I get a bunch of e.g. touchesBegan events. If I keep those fingers down and put down one more, I get no events at all (not even touchesCancelled). I've been looking at functionality of some games and I see that they somehow detect that there's been a 6th touch and do things like reset "button is pressed" states, which would be perfect. If there's some other notification or event that I need, I can't seem to find it.

Edit: Ok well it seems that I spelled it "touchesCanceled" and not "touchesCancelled" in the code so that's probably what's going on. Doh!

HiriseSoftware fucked around with this message at 05:56 on Dec 15, 2014

Adbot
ADBOT LOVES YOU

Just-In-Timeberlake
Aug 18, 2003
I'm having a weird issue and for the life of me I can't get the right combination of terms in google to find a solution. I'm relatively new to this so the answer is probably right in front of my face but who knows.

I'm using the SWTableViewCell project to fill a UITableView with data fetched from a webpage in an asyncronous call

code:
-(void) viewDidAppear:(BOOL)animated {
    [super viewDidAppear:animated];
    
    //SHOW A LOADING ANIMATION
    hud = [MBProgressHUD showHUDAddedTo:self.view animated:YES];
    hud.mode = MBProgressHUDModeIndeterminate;
    hud.labelText = @"Loading...";
    [hud show:YES];
    
    [hud showWhileExecuting:@selector(setUpView) onTarget:self withObject:nil animated:YES]; //setUpView is a function that gets the data and is called asyncronously

}
In setUpView I have tried every method I can find to reload the table, for example, like so

code:
	[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
    	[self.tableView performSelectorOnMainThread:@selector(layoutIfNeeded) withObject:nil waitUntilDone:NO];
If I call setUpView from viewDidLoad in the main thread everything works fine, asyncronously the table remains blank until I click a button that takes me to another view, then the table shows up briefly before the segue fires.

There is a UIScrollViewDelegate like so that does not get fired when the call to setUpView is asyncronous (but does get hit if called from the main thread), but does get hit right before the segue

code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    if (self.useCustomCells)
    {
        CustomTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:@"UMCell" forIndexPath:indexPath];
        
        // optionally specify a width that each set of utility buttons will share
        [cell setLeftUtilityButtons:[self leftButtons] WithButtonWidth:32.0f];
        [cell setRightUtilityButtons:[self rightButtons] WithButtonWidth:58.0f];
        cell.delegate = self;
        
        cell.label.text = @"some stuff";
        
        return cell;
    }
    else
    {
        static NSString *cellIdentifier = @"Cell";
        
        SWTableViewCell *cell = (SWTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
        
        if (cell == nil) {
            
            cell = [[SWTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
            
            cell.leftUtilityButtons = [self leftButtons];
            cell.rightUtilityButtons = [self rightButtons];
            cell.delegate = self;
        }
        
        Vehicle *vehicle = _testArray[indexPath.section][indexPath.row]; //Vehicle is a custom class
        
        cell.textLabel.text = [[[NSArray alloc] initWithObjects:vehicle.year, vehicle.make, vehicle.model, nil] componentsJoinedByString:@" "];
        cell.textLabel.backgroundColor = [UIColor whiteColor];
        cell.detailTextLabel.backgroundColor = [UIColor whiteColor];
        cell.detailTextLabel.text = [[[NSArray alloc] initWithObjects:vehicle.license, vehicle.vin, nil] componentsJoinedByString:@" / "];
        
        return cell;
    }
    
}
Any idea what the problem might be?

Danyull
Jan 16, 2011

So I recently decided to start learning Objective-C so that I can make iOS apps, and it's pretty fun so far, but I'm having trouble with the iOS simulator in Xcode. When I'm messing with the View, I can see the entire iPhone screen, but when I run the simulator it's cut off at the right and bottom:

The View (incredibly zoomed out so you can see that the entire thing is visible):


The Simulator:


If anyone could tell me how to fix this, I'd really appreciate it.

brap
Aug 23, 2004

Grimey Drawer

Danyull posted:

So I recently decided to start learning Objective-C so that I can make iOS apps, and it's pretty fun so far, but I'm having trouble with the iOS simulator in Xcode. When I'm messing with the View, I can see the entire iPhone screen, but when I run the simulator it's cut off at the right and bottom:

The View (incredibly zoomed out so you can see that the entire thing is visible):


The Simulator:


If anyone could tell me how to fix this, I'd really appreciate it.

Check your constraints.

NoDamage
Dec 2, 2000
Is this the first year that they've permitted pricing changes during the iTunes Connect shutdown? I seem to recall them warning against changing your price in the previous years emails.

quote:

During this time, you will not be able to submit new apps, app updates, or In-App Purchases. You also will not be able to access iTunes Connect or make changes to TestFlight Beta Testing. You can schedule an app release or price changes to take place between December 22 and December 29. Just make sure that your changes are scheduled, submitted, and approved by December 18, to ensure your app remains available during this busy period.

Danyull
Jan 16, 2011

fleshweasel posted:

Check your constraints.

I tried adding the suggested constraints, and now when I run it, the simulator squeezes the last button on the right to make it fit. Is there any way to just make the view be the right size instead of having to adjust it until the simulator doesn't do that? Thank you for your help.

brap
Aug 23, 2004

Grimey Drawer
So I take it that the cards are individual views? They should probably be constrained to have equal widths and heights. Although I'm not familiar enough with complex constraints to be sure what's best for a large set of identical elements like that.

edit: it may work well to constrain them to have equal widths and constrain them to have a particular aspect ratio.

dc3k
Feb 18, 2003

what.

Danyull posted:

I tried adding the suggested constraints
This is generally not a good idea. Do you want them all to always be the same width, or always have the same spacing between them but a variable width? If you have the same spacing between them, no matter the screen size, their widths will change, but you'll always fill up as much width as possible.

Just-In-Timeberlake posted:

Any idea what the problem might be?

You can try using GCD instead of performSelectorOnMainThread
code:
dispatch_async(dispatch_get_main_queue(), ^{
//things you want on the main thread
});

dc3k fucked around with this message at 05:16 on Dec 16, 2014

brap
Aug 23, 2004

Grimey Drawer
I'm looking into how to create an iPad version of my app. Right now I have a tab controller at the root of my iPhone storyboard.

What I think I want for the iPad version is a split view controller that has 3 of the tabs of the tab controller as the master view controller, and the last tab of the tab controller as the detail view. Do size classes allow you to change the layout and/or initial view controller of the storyboard, or are you limited to just changing the presence and values of views inside view controllers?

The iPhone should remain totally tab bar-based. The detail view's state doesn't particularly depend on what you do in the master view: they are generally just complementary to each other. Is there another technique I should be using? Should I look at maintaining separate iPad and iPhone storyboards?

The lazy alternative, I guess, is to just have a giant version of the iPhone app. I would feel bad about that though. Does Apple outright reject those?

Doctor w-rw-rw-
Jun 24, 2008

fleshweasel posted:

I'm looking into how to create an iPad version of my app. Right now I have a tab controller at the root of my iPhone storyboard.

What I think I want for the iPad version is a split view controller that has 3 of the tabs of the tab controller as the master view controller, and the last tab of the tab controller as the detail view. Do size classes allow you to change the layout and/or initial view controller of the storyboard, or are you limited to just changing the presence and values of views inside view controllers?

The iPhone should remain totally tab bar-based. The detail view's state doesn't particularly depend on what you do in the master view: they are generally just complementary to each other. Is there another technique I should be using? Should I look at maintaining separate iPad and iPhone storyboards?

The lazy alternative, I guess, is to just have a giant version of the iPhone app. I would feel bad about that though. Does Apple outright reject those?

Screenshots would help suggestions more than any description. Mind providing one?

brap
Aug 23, 2004

Grimey Drawer



Here's a proof of concept I have. Very sloppy at the moment. During the day there would be actual arrival times. When you select a bus stop, the table of routes comes up. The favorites view is always on the left. Not sure if it's any good considering the routes table is so stretched, but most bus stops have between 2-4 routes so it's not great to make it a column.

The iPhone version is simpler and just has the map view here as another tab in the tab controller.

Doctor w-rw-rw-
Jun 24, 2008
Hmm. As a longtime iPad and iPad mini user, most people on the go are going to use it in portrait mode on a mini, though on the bigger models, landscape might be more common depending on the cover. The layout isn't a bad start, though that's not to exclude the possibility of something better.

As for how you organize your storyboards - I don't know, because I kill them whenever possible. Apple's APIs are typically pretty awesome to consume from code so it baffles me just how quickly they've managed to make Interface Builder total poo poo. :( Nothing lasts forever, I guess.

Just-In-Timeberlake
Aug 18, 2003

status posted:


You can try using GCD instead of performSelectorOnMainThread
code:
dispatch_async(dispatch_get_main_queue(), ^{
//things you want on the main thread
});

Just tried it, no dice. Here is a video of what I'm talking about, you can see where the table's UIScrollViewDelegate gets called when I click the "+Add Vehicle" button and loads the table just before the segue fires.

https://www.youtube.com/watch?v=7AR8HoVa8xg

Doc Block
Apr 15, 2003
Fun Shoe
You should still be using dispatch_async() instead of performSelectorOnMainThread.

Try it without the MBProgressHUD stuff.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Doc Block posted:

You should still be using dispatch_async() instead of performSelectorOnMainThread.

Why?

Just-In-Timeberlake
Aug 18, 2003

Doc Block posted:

You should still be using dispatch_async() instead of performSelectorOnMainThread.

Try it without the MBProgressHUD stuff.

No such luck

dc3k
Feb 18, 2003

what.

Just-In-Timeberlake posted:

Just tried it, no dice. Here is a video of what I'm talking about, you can see where the table's UIScrollViewDelegate gets called when I click the "+Add Vehicle" button and loads the table just before the segue fires.

https://www.youtube.com/watch?v=7AR8HoVa8xg

What UIScrollViewDelegate method is being called?

GCD is much better at managing threads than you are. Just give it a task and let the system figure it out - that's why it exists. Neat article here!. Another obvious plus in the case of performSelectorOnMainThread is that you don't have to have a method with a single parameter and wrap all your objects up into one bullshit object and unwrap it later. You can have normal method names that take as many parameters as you want.

Doc Block
Apr 15, 2003
Fun Shoe

status posted:

GCD is much better at managing threads than you are. Just give it a task and let the system figure it out - that's why it exists. Neat article here!. Another obvious plus in the case of performSelectorOnMainThread is that you don't have to have a method with a single parameter and wrap all your objects up into one bullshit object and unwrap it later. You can have normal method names that take as many parameters as you want.

Pretty much what status wrote. Don't worry about threads, just GCD queueueueueueues. Plus it's nice not having to needlessly break something out into a separate method that I would otherwise keep inline just so I can call -performSelectorOnMainThread:.

Doc Block
Apr 15, 2003
Fun Shoe

This kind of thing reeks of doing UI stuff off the main queue, but that's just a hunch.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

Doc Block posted:

Pretty much what status wrote. Don't worry about threads, just GCD queueueueueueues. Plus it's nice not having to needlessly break something out into a separate method that I would otherwise keep inline just so I can call -performSelectorOnMainThread:.

I'm with you both on the general points here. I was interested in the specific question: why is dispatch_async(dispatch_get_main_queue(), ^{ [self doIt]; }) better than [self performSelectorOnMainThread:@selector(doIt)]? They look pretty similar to me.

If it's just an overall "prefer GCD to performSelector/NSThread" that's cool. I thought maybe I was missing something.

Doc Block
Apr 15, 2003
Fun Shoe
In this case, this
Objective-C code:
dispatch_async(dispatch_get_main_queue(), ^{
    [self.tableView reloadData];
    [self.tableView layoutSubviews];    // shouldn't be needed to just have correctly sized table view cells etc. but whatever
 });
seems cleaner than
Objective-C code:
[self.tableView performSelectorOnMainThread:@selector(reloadData) withObject:nil waitUntilDone:NO];
[self.tableView performSelectorOnMainThread:@selector(layoutSubviews) withObject:nil waitUntilDone:NO];

Doc Block
Apr 15, 2003
Fun Shoe
Just-in-Timberlake: the part where you say -setupView works when called from -viewDidLoad but not "asynchronously" makes me think your issue is that you've missed something re: only doing UI stuff on the main queue. Instead of writing -setupView to work from any queue or thread, go through and make sure any calls to -setupView only happen on the main queue by wrapping them with dispatch_async(). Then put something like:
Objective-C code:
if([NSThread isMainThread] == NO) {
   NSLog(@"Whoops! Got called from a background thread/queue!");
}
at the start of -setupView to see if you've missed any calls you need to wrap.

Or you could even do it like
Objective-C code:
- (void)setupView
{
    // check fuckingblocksyntax.com for actual syntax
    block setupBlock = ^{
        // code that sets up your view
    };
    if([NSThread isMainThread]) {
        setupBlock();
    } else {
        dispatch_async(dispatch_get_main_queue(), setupBlock);
        NSLog(@"%s: called from somewhere other than main queue!", __PRETTY_FUNCTION__);
    }
}
if you want to be super paranoid, or have a method that you need to always do its work on the main queue but don't want to wrap in dispatch_async() or -performSelectorOnMainThread:

Doc Block fucked around with this message at 08:56 on Dec 17, 2014

Doc Block
Apr 15, 2003
Fun Shoe
Also, when you're downloading data asynchronously, Apple doesn't guarantee your completion block will be called on the main queue IIRC, so unless you're using a library that does guarantee it, wrap anything inside your download completion block that needs to happen on the main queue (such as all UI stuff) in dispatch_async().

ultramiraculous
Nov 12, 2003

"No..."
Grimey Drawer

pokeyman posted:

I'm with you both on the general points here. I was interested in the specific question: why is dispatch_async(dispatch_get_main_queue(), ^{ [self doIt]; }) better than [self performSelectorOnMainThread:@selector(doIt)]? They look pretty similar to me.

If it's just an overall "prefer GCD to performSelector/NSThread" that's cool. I thought maybe I was missing something.

It's a scheduling issue. -performSelectorOnMainThread basically creates a timer with 0 duration in NSDefaultRunLoopMode. If the user is, say, scrolling at the time, then UI changes aren't going to take effect. The CGD queue is basically more likely to fire sooner.

You basically get the same effect if you go all the way to -performSelectorOnMainThread:withObject:waitUntilDone:modes: and choose NSRunLoopCommonModes.

Doctor w-rw-rw-
Jun 24, 2008

pokeyman posted:

I'm with you both on the general points here. I was interested in the specific question: why is dispatch_async(dispatch_get_main_queue(), ^{ [self doIt]; }) better than [self performSelectorOnMainThread:@selector(doIt)]? They look pretty similar to me.

If it's just an overall "prefer GCD to performSelector/NSThread" that's cool. I thought maybe I was missing something.
Is it ever a good idea to use 'performSelector*' methods? Aren't they bad for ARC or non-object parameters?

Paging rjmccall - I think he's answered this before.

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

ultramiraculous posted:

It's a scheduling issue. -performSelectorOnMainThread basically creates a timer with 0 duration in NSDefaultRunLoopMode. If the user is, say, scrolling at the time, then UI changes aren't going to take effect. The CGD queue is basically more likely to fire sooner.

You basically get the same effect if you go all the way to -performSelectorOnMainThread:withObject:waitUntilDone:modes: and choose NSRunLoopCommonModes.

That's a good point, I hadn't thought of that.

Doctor w-rw-rw- posted:

Is it ever a good idea to use 'performSelector*' methods? Aren't they bad for ARC or non-object parameters?

Paging rjmccall - I think he's answered this before.

Wouldn't surprise me if they suck, and you do need to silence compiler warnings to use them with ARC.

I don't want to give anyone the wrong impression here, I'm not trying to mount a defense of the -performSelector... family of methods. It's more of a thought experiment and making sure I understand stuff.

Just-In-Timeberlake
Aug 18, 2003

Doc Block posted:

Just-in-Timberlake: the part where you say -setupView works when called from -viewDidLoad but not "asynchronously" makes me think your issue is that you've missed something re: only doing UI stuff on the main queue. Instead of writing -setupView to work from any queue or thread, go through and make sure any calls to -setupView only happen on the main queue by wrapping them with dispatch_async(). Then put something like:
Objective-C code:
if([NSThread isMainThread] == NO) {
   NSLog(@"Whoops! Got called from a background thread/queue!");
}
if you want to be super paranoid, or have a method that you need to always do its work on the main queue but don't want to wrap in dispatch_async() or -performSelectorOnMainThread:

So I've done this, and as far as I can see all the UI stuff is being performed on the main thread but that initial show isn't happening

Objective-C code:
- (void)viewDidLoad {
    [super viewDidLoad];
    
    dispatch_async(dispatch_get_main_queue(), ^{
        [self setUpView];
        
        if([NSThread isMainThread] == NO) {
            NSLog(@"Whoops! Got called from a background thread/queue!");
        } else {
            NSLog(@"Main thread");
        }
        
        //[MBProgressHUD hideHUDForView:self.view animated:YES];
    });
}
Here is the UIScrollDelegate that isn't fired on initial load that builds the cells for the table

Objective-C code:
#pragma mark - UIScrollViewDelegate

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *cellIdentifier = @"Cell";
    
    SWTableViewCell *cell = (SWTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    
    if (cell == nil) {
        
        cell = [[SWTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
        
        cell.leftUtilityButtons = [self leftButtons];
        cell.rightUtilityButtons = [self rightButtons];
        cell.delegate = self;
    }
    
    Vehicle *vehicle = _testArray[indexPath.section][indexPath.row];
    
    //NSDate *dateObject = _testArray[indexPath.section][indexPath.row];
    cell.textLabel.text = [[[NSArray alloc] initWithObjects:vehicle.year, vehicle.make, vehicle.model, nil] componentsJoinedByString:@" "];
    cell.textLabel.backgroundColor = [UIColor whiteColor];
    cell.detailTextLabel.backgroundColor = [UIColor whiteColor];
    cell.detailTextLabel.text = [[[NSArray alloc] initWithObjects:vehicle.license, vehicle.vin, nil] componentsJoinedByString:@" / "];
    
    return cell;
}
Near as I can tell "_testArray" hasn't been filled yet in the call to the webpage by the time the code that creates the cells looks at it so it never calls this. When I move to another screen "_testArray" has been populated so this gets called.

Doc Block
Apr 15, 2003
Fun Shoe
Ok, first of all, viewDidLoad will only ever be called on the main thread you don't need to wrap UI stuff that's in viewDidLoad with dispatch_async(). I meant put the NSThread stuff in setupView, and then only call setupView from the main thread.

Why do you keep calling your table view a scroll view? Yes, UITableView inherits from UIScrollView, but they aren't the same thing. And a UIScrollView's delegate is very different than a UITableView's delegate or dataSource.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Doctor w-rw-rw- posted:

Is it ever a good idea to use 'performSelector*' methods? Aren't they bad for ARC or non-object parameters?

Paging rjmccall - I think he's answered this before.

It's a general rule (i.e. it's true even outside of ARC) that the method you call has to have a very specific signature involving just pointer types; as an additional promise, it's allowed to return void, but you have to be careful about that in ARC, because performSelector says it returns id, and if you accidentally do anything with that id, ARC's builtin paranoia about performSelector might evaporate and you'll end up "managing" a bunch of garbage bits. Also, as an extra rule in ARC, if the method you call does return an object, it had better return it at +0.

dc3k
Feb 18, 2003

what.

Just-In-Timeberlake posted:

Objective-C code:
#pragma mark - UIScrollViewDelegate

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    static NSString *cellIdentifier = @"Cell";
    
    SWTableViewCell *cell = (SWTableViewCell *)[tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    
    if (cell == nil) {
        
        cell = [[SWTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
        
        cell.leftUtilityButtons = [self leftButtons];
        cell.rightUtilityButtons = [self rightButtons];
        cell.delegate = self;
    }
    
    Vehicle *vehicle = _testArray[indexPath.section][indexPath.row];
    
    //NSDate *dateObject = _testArray[indexPath.section][indexPath.row];
    cell.textLabel.text = [[[NSArray alloc] initWithObjects:vehicle.year, vehicle.make, vehicle.model, nil] componentsJoinedByString:@" "];
    cell.textLabel.backgroundColor = [UIColor whiteColor];
    cell.detailTextLabel.backgroundColor = [UIColor whiteColor];
    cell.detailTextLabel.text = [[[NSArray alloc] initWithObjects:vehicle.license, vehicle.vin, nil] componentsJoinedByString:@" / "];
    
    return cell;
}

As an aside to your threading issues, dequeueReusableCellWithIdentifier:forIndexPath: will always return a valid cell. You don't need to test for nil. This code looks like you're following a fairly old tutorial. I would also use stringWithFormat: instead of creating an array and using componentsJoinedByString:

Doh004
Apr 22, 2007

Mmmmm Donuts...
Help! This is really weird and I'm not sure to what to do.

My check for iOS version compatibility works in 2/3 of my targets:

code:
let checkCompatibility: AnyClass = NSClassFromString("UIAlertController")
Basically says if the UIAlertController exists (which is doesn't in iOS7). This works fine in my two main targets. The third, one I use for Ad Hoc Builds (yes it's its own target) will return true/not nil while running in iOS7. I have no idea why!

I even do this before hand for my own sanity:

code:
NSLog(UIDevice.currentDevice().systemVersion)
Which says which version of the OS I'm using. I've triple checked my build settings and the settings are nearly identical between the two targets (aside from an additional macro setting). Am I missing something huge here because this seems funky as hell.

brap
Aug 23, 2004

Grimey Drawer
I have dealt with that exact issue in swift. I wrote an obj-c static method just for that check and it worked without fuss.

Doh004
Apr 22, 2007

Mmmmm Donuts...
Found it!

Changing the Optimization Level from 'Fastest [-O]' to 'None [-Onone]' allows the check to work properly. My Ad Hoc build was set to Fastest. Is this intended?

What scares me is my Release config is also set to fastest, so would this not work on my app store submitted application?

Doc Block
Apr 15, 2003
Fun Shoe
Your Release config should always be set to fastest or whatever.

This is why you should always be sure to also test your app with Release config.

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe
We currently assume types always exist. It's a known limitation; we know we need better deployment-testing logic and are working in it. For now, don't disable optimization, just guard your version-specific code with an opaque check.

Doh004
Apr 22, 2007

Mmmmm Donuts...
What do you mean by an opaque check? Like checking the actual system version instead?

rjmccall
Sep 7, 2007

no worries friend
Fun Shoe

Doh004 posted:

What do you mean by an opaque check? Like checking the actual system version instead?

That or what fleshweasel suggested, checking for the weak symbol in an ObjC function. It's not pretty, I know.

kode54
Nov 26, 2007

aka kuroshi
Fun Shoe
Anyone feel like helping with this silly issue?

Apparently, it's perfectly natural to expect ID3v1 tags to support internationalization. So my fork of Cog now has a filed issue, that it's not using the "system codepage" to decode the tags from the poster's Russian encoded tags, which are in the Windows codepage 1251 encoding.

I can add a configuration option, assuming there's a handy way to detect supported encodings from the system and a handy way to convert 8 bit encodings to UTF-8, but I'm not exactly sure how to do either of those things, or for a better option, detecting the system locale and supporting that directly. The existing code just treats all of these unknown encoded tags as latin1.

Doh004
Apr 22, 2007

Mmmmm Donuts...

rjmccall posted:

That or what fleshweasel suggested, checking for the weak symbol in an ObjC function. It's not pretty, I know.

Oh okay, gotcha! Good to know and thanks for the clarification as always rjmccall.

Adbot
ADBOT LOVES YOU

pokeyman
Nov 26, 2006

That elephant ate my entire platoon.

kode54 posted:

Anyone feel like helping with this silly issue?

Apparently, it's perfectly natural to expect ID3v1 tags to support internationalization. So my fork of Cog now has a filed issue, that it's not using the "system codepage" to decode the tags from the poster's Russian encoded tags, which are in the Windows codepage 1251 encoding.

I can add a configuration option, assuming there's a handy way to detect supported encodings from the system and a handy way to convert 8 bit encodings to UTF-8, but I'm not exactly sure how to do either of those things, or for a better option, detecting the system locale and supporting that directly. The existing code just treats all of these unknown encoded tags as latin1.

+[NSLocale currentLocale] might be helpful if you have a list of default fallbacks ("the current locale is Russia, let's use win-1251 as our fallback encoding"). As for converting between encodings, you want to get an NSString (e.g. via -[NSString initWithData:encoding:]) and then write it back out via -dataUsingEncoding:. The list of supported encodings is +[NSString availableStringEncodings].

Please let me know if this isn't helpful, I'm having a hard time gauging what level to answer at.

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